一个 MariaDB 存储过程中检查表的参数被解释为表字段。

huangapple go评论108阅读模式
英文:

A MariaDB stored procedure parameter checking for a table is being interpreted as a table field

问题

  1. 我有一个Drupal数据库MariaDB 10.4.17),我试图只在以下情况下替换字段中的字符串:
  2. 1. 目标表存在;以及
  3. 2. 字段中的一个值包含特定值
  4. 然而,当我运行这段代码时,它会抛出错误“未知列'my_table''字段列表'中”,从我所读到的内容来看,这似乎是在表内查找一个具有该名称的*字段*,但找不到它。
  5. 这是为什么,以及我如何使代码在`THEN`块中仅在表存在时才执行?
  6. ---
  7. **更新**
  8. 我尝试了@danblack的答案,无论我传递的表名是否存在,都会得到相同的错误:
  9. “未知列'my_table''字段列表'中”。
  10. 看起来有两个问题:
  11. 1. 我试图使用过程参数作为字段名的变量,正如Dan所指出的
  12. 2. 我还传递了没有引号的参数,尽管它们是字符串,所以它们没有被解释为字符串。
  13. 现在它完全按预期工作:
  14. ```sql
  15. USE myDatabase;
  16. DELIMITER $$
  17. CREATE OR REPLACE PROCEDURE replaceLinks(
  18. tableName VARCHAR(255),
  19. fieldValue VARCHAR(255),
  20. fieldFormat VARCHAR(255)
  21. )
  22. BEGIN
  23. DECLARE EXIT HANDLER FOR 1146 SELECT 1;
  24. DECLARE EXIT HANDLER FOR 1054 SELECT 1;
  25. EXECUTE IMMEDIATE CONCAT(
  26. 'UPDATE ',
  27. tableName,
  28. ' SET ',
  29. fieldValue,
  30. ' = REPLACE(',
  31. fieldValue,
  32. ',\'TARGET_STR\', \'REPLACE_STR\') WHERE ',
  33. fieldFormat,
  34. ' = \'html\''
  35. );
  36. END
  37. $$
  38. DELIMITER ;
  39. CALL replaceLinks(
  40. 'my_table', 'field_value', 'field_format'
  41. );
  1. <details>
  2. <summary>英文:</summary>
  3. I&#39;ve got a Drupal database (MariaDB 10.4.17), and I&#39;m trying to replace a string in a field only if:
  4. 1. The target table exists; and
  5. 2. One of the field values within contains a specific value
  6. However when I run this, it throws the error `Unknown column &#39;my_table&#39; in &#39;field list&#39;`, which from what I&#39;ve read suggests it is looking within a table for a *field* with that name and can&#39;t find it.
  7. Why is this happening, and how can I make the code in the `THEN` block execute on a table only if it exists?
  8. ```sql
  9. USE myDatabase;
  10. DELIMITER $$
  11. CREATE PROCEDURE replaceLinks(
  12. tableName VARCHAR(255),
  13. fieldValue VARCHAR(255),
  14. fieldFormat VARCHAR(255)
  15. )
  16. BEGIN
  17. IF EXISTS (
  18. SELECT *
  19. FROM tableName
  20. ) THEN
  21. UPDATE tableName
  22. SET fieldValue = REPLACE(
  23. fieldValue,
  24. &#39;TARGET_STR&#39;,
  25. &#39;REPLACE_STR&#39;
  26. )
  27. WHERE fieldFormat = &#39;html&#39;
  28. END IF
  29. END
  30. DELIMITER ;
  31. CALL replaceLinks(
  32. my_table field_value field_format
  33. );

UPDATE

I tried with @danblack's answer, and still get the same error whether the table name I pass existed or not:
Unknown column &#39;my_table&#39; in &#39;field list&#39;.

It looks like there was 2 issues at work:

  1. I was trying to use procedure parameters as variables for field names, as Dan noted; and
  2. 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:

  1. USE myDatabase;
  2. DELIMITER $$
  3. CREATE OR REPLACE PROCEDURE replaceLinks(
  4. tableName VARCHAR(255),
  5. fieldValue VARCHAR(255),
  6. fieldFormat VARCHAR(255)
  7. )
  8. BEGIN
  9. DECLARE EXIT HANDLER FOR 1146 SELECT 1;
  10. DECLARE EXIT HANDLER FOR 1054 SELECT 1;
  11. EXECUTE IMMEDIATE CONCAT(
  12. &#39;UPDATE &#39;,
  13. tableName,
  14. &#39; SET &#39;,
  15. fieldValue,
  16. &#39; = REPLACE(&#39;,
  17. fieldValue,
  18. &#39;,\&#39;TARGET_STR\&#39;, \&#39;REPLACE_STR\&#39;) WHERE &#39;,
  19. fieldFormat,
  20. &#39; = \&#39;html\&#39;&#39;
  21. );
  22. END
  23. $$
  24. DELIMITER ;
  25. CALL replaceLinks(
  26. &#39;my_table&#39;, &#39;field_value&#39;, &#39;field_format&#39;
  27. );

答案1

得分: 3

存储过程参数不能用作字段名的变量 SQL 语法。

你可以使用 EXECUTE IMMEDIATE 的魔法来构建一个查询:

  1. CREATE OR REPLACE PROCEDURE replaceLinks(tableName VARCHAR(255),
  2. fieldValue VARCHAR(255),
  3. fieldFormat VARCHAR(255) )
  4. EXECUTE IMMEDIATE CONCAT('UPDATE ',
  5. tableName,
  6. ' SET ',
  7. fieldValue,
  8. ' = REPLACE(',
  9. fieldValue,
  10. ',\'TARGET_STR\', \'REPLACE_STR\') WHERE ',
  11. fieldFormat,
  12. ' = \'html\'');

处理未找到的情况可以使用 DECLARE HANDLER

  1. BEGIN
  2. DECLARE EXIT HANDLER FOR 1146 SELECT 1;
  3. EXECUTE IMMEDIATE ....;
  4. 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:

  1. CREATE OR REPLACE PROCEDURE replaceLinks(tableName VARCHAR(255),
  2. fieldValue VARCHAR(255),
  3. fieldFormat VARCHAR(255) )
  4. EXECUTE IMMEDIATE CONCAT(&#39;UPDATE &#39;,
  5. tableName,
  6. &#39; SET &#39;,
  7. fieldValue,
  8. &#39; = REPLACE(&#39;,
  9. fieldValue,
  10. &#39;,\&#39;TARGET_STR\&#39;, \&#39;REPLACE_STR\&#39;) WHERE &#39;,
  11. fieldFormat,
  12. &#39; = \&#39;html\&#39;&#39;);

To handle the not found use the DECLARE HANDLER.

  1. BEGIN
  2. DECLARE EXIT HANDLER FOR 1146 SELECT 1;
  3. EXECUTE IMMEDIATE ....;
  4. END$$

huangapple
  • 本文由 发表于 2023年3月23日 09:20:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75818524.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定