英文:
A MariaDB stored procedure parameter checking for a table is being interpreted as a table field
问题
我有一个Drupal数据库(MariaDB 10.4.17),我试图只在以下情况下替换字段中的字符串:
1. 目标表存在;以及
2. 字段中的一个值包含特定值
然而,当我运行这段代码时,它会抛出错误“未知列'my_table'在'字段列表'中”,从我所读到的内容来看,这似乎是在表内查找一个具有该名称的*字段*,但找不到它。
这是为什么,以及我如何使代码在`THEN`块中仅在表存在时才执行?
---
**更新**
我尝试了@danblack的答案,无论我传递的表名是否存在,都会得到相同的错误:
“未知列'my_table'在'字段列表'中”。
看起来有两个问题:
1. 我试图使用过程参数作为字段名的变量,正如Dan所指出的;
2. 我还传递了没有引号的参数,尽管它们是字符串,所以它们没有被解释为字符串。
现在它完全按预期工作:
```sql
USE myDatabase;
DELIMITER $$
CREATE OR REPLACE PROCEDURE replaceLinks(
        tableName VARCHAR(255),
        fieldValue VARCHAR(255),
        fieldFormat VARCHAR(255)
    ) 
    BEGIN
        DECLARE EXIT HANDLER FOR 1146 SELECT 1;
        DECLARE EXIT HANDLER FOR 1054 SELECT 1;
        EXECUTE IMMEDIATE CONCAT(
            'UPDATE ',
            tableName,
            ' SET ',
            fieldValue,
            ' = REPLACE(',
            fieldValue,
            ',\'TARGET_STR\', \'REPLACE_STR\') WHERE ',
            fieldFormat,
            ' = \'html\''
        );
    END
$$
DELIMITER ;
CALL replaceLinks(
        'my_table', 'field_value', 'field_format'
    );
<details>
<summary>英文:</summary>
I've got a Drupal database (MariaDB 10.4.17), and I'm trying to replace a string in a field only if:
 1. The target table exists; and
 2. One of the field values within contains a specific value
However when I run this, it throws the error `Unknown column 'my_table' in 'field list'`, which from what I've read suggests it is looking within a table for a *field* with that name and can't find it.
Why is this happening, and how can I make the code in the `THEN` block execute on a table only if it exists?
```sql
USE myDatabase;
DELIMITER $$
CREATE PROCEDURE replaceLinks(
    tableName VARCHAR(255),
    fieldValue VARCHAR(255),
    fieldFormat VARCHAR(255)
)
BEGIN
    IF EXISTS (
        SELECT *
        FROM tableName
    ) THEN
        UPDATE tableName
        SET fieldValue = REPLACE(
                fieldValue,
                'TARGET_STR',
                'REPLACE_STR'
            )
        WHERE fieldFormat = 'html'
    END IF
END
DELIMITER ;
CALL replaceLinks(
    my_table field_value field_format
);
UPDATE
I tried with @danblack's answer, and still get the same error whether the table name I pass existed or not:
Unknown column 'my_table' in 'field list'.
It looks like there was 2 issues at work:
- I was trying to use procedure parameters as variables for field names, as Dan noted; and
 - I was also passing the parameters without quotes despite them being strings, so they were not interpreted as such.
 
This now works exactly as intended:
USE myDatabase;
DELIMITER $$
CREATE OR REPLACE PROCEDURE replaceLinks(
        tableName VARCHAR(255),
        fieldValue VARCHAR(255),
        fieldFormat VARCHAR(255)
    ) 
    BEGIN
        DECLARE EXIT HANDLER FOR 1146 SELECT 1;
        DECLARE EXIT HANDLER FOR 1054 SELECT 1;
        EXECUTE IMMEDIATE CONCAT(
            'UPDATE ',
            tableName,
            ' SET ',
            fieldValue,
            ' = REPLACE(',
            fieldValue,
            ',\'TARGET_STR\', \'REPLACE_STR\') WHERE ',
            fieldFormat,
            ' = \'html\''
        );
    END
$$
DELIMITER ;
CALL replaceLinks(
        'my_table', 'field_value', 'field_format'
    );
答案1
得分: 3
存储过程参数不能用作字段名的变量 SQL 语法。
你可以使用 EXECUTE IMMEDIATE 的魔法来构建一个查询:
CREATE OR REPLACE PROCEDURE replaceLinks(tableName VARCHAR(255),
  fieldValue VARCHAR(255),
  fieldFormat VARCHAR(255) )
EXECUTE IMMEDIATE CONCAT('UPDATE ',
  tableName,
  ' SET ',
  fieldValue,
  ' = REPLACE(',
  fieldValue,
  ',\'TARGET_STR\', \'REPLACE_STR\') WHERE ',
  fieldFormat,
  ' = \'html\'');
处理未找到的情况可以使用 DECLARE HANDLER。
BEGIN
DECLARE EXIT HANDLER FOR 1146 SELECT 1;
EXECUTE IMMEDIATE ....;
END$$
英文:
Procedure arguments cannot be used as variables SQL syntax for field names.
What you can do is using the magic of EXECUTE IMMEDIATE to construct a query:
CREATE OR REPLACE PROCEDURE replaceLinks(tableName VARCHAR(255),
  fieldValue VARCHAR(255),
  fieldFormat VARCHAR(255) )
EXECUTE IMMEDIATE CONCAT('UPDATE ',
  tableName,
  ' SET ',
  fieldValue,
  ' = REPLACE(',
  fieldValue,
  ',\'TARGET_STR\', \'REPLACE_STR\') WHERE ',
  fieldFormat,
  ' = \'html\'');
To handle the not found use the DECLARE HANDLER.
BEGIN
DECLARE EXIT HANDLER FOR 1146 SELECT 1;
EXECUTE IMMEDIATE ....;
END$$
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论