【问题标题】:MySQL syntax error when using prepared statement with CONCAT将准备好的语句与 CONCAT 一起使用时 MySQL 语法错误
【发布时间】:2019-12-03 17:56:40
【问题描述】:

我正在尝试在存储过程中使用准备好的语句。我在初始 SET @idToUpdateQuery 中遇到语法错误。我已经知道 CONCAT 没有使用 := 进行变量赋值的工作正常,因为它在其他地方使用并按预期工作。本质上,我只需要能够将准备好的 SELECT 语句的结果放入变量@resultId 中。有问题的代码如下:

SET @distinctTableXIds = (SELECT COUNT(*) FROM tempTableX);

 SET @i = 0;
 WHILE @i < @distinctTableXIds DO

    /*CONCAT IS NEEDED HERE TO PASS USER DEFINED @i*/
    SET @idToUpdateQuery = CONCAT('SELECT @result := MAX(id) 
    FROM tableY 
    WHERE tableZId = (SELECT id FROM tempTableX ORDER BY id LIMIT ', @i, ', 1)');

    PREPARE @IdToUpdateStmt FROM @IdToUpdateQuery;
    EXECUTE @IdToUpdateStmt;

    SET @resultId = SELECT @result;

    UPDATE tableY
    SET someBoolean = 1
    WHERE id = @resultId;

    SET @i = @i + 1;

 END WHILE;

【问题讨论】:

  • SET @idToUpdateQuery = CONCAT(..); 中没有语法错误。但是PREPARE @IdToUpdateStmt FROM @IdToUpdateQuery; 看起来不正确。尝试不使用@
  • 在盯着这个至少一个小时之后,我在刷新这个页面之前得出了同样的结论。谢谢。

标签: mysql stored-procedures prepared-statement variable-assignment do-while


【解决方案1】:

您不使用@ 符号作为语句名称。它不是用户变量。

参见https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html的示例

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;

除此之外,我认为您根本不需要为此任务准备好声明。我能想到至少两个其他的解决方案。给我几分钟,我会写一篇。


使用光标的一种解决方案(请参阅https://dev.mysql.com/doc/refman/8.0/en/cursors.html):

BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE max_id INT;
  DECLARE cur1 CURSOR FOR SELECT MAX(id) FROM tableY JOIN tempTableX ON (tableY.tableZId = temptableX.id) GROUP BY tableZId;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;

  read_loop: LOOP
    FETCH cur1 INTO max_id
    IF done THEN
      LEAVE read_loop;
    END IF;
    UPDATE tableY SET someBoolean = 1 WHERE id = max_id;
  END LOOP;

  CLOSE cur2;
END

在一个 UPDATE 语句中完成所有操作的另一种解决方案:

UPDATE tableY AS y1
INNER JOIN tempTableX AS x ON (y1.tableZId = x.id)
LEFT OUTER JOIN tableY AS y2 ON (y1.tableZId = y2.tableZId AND y1.id < y2.id)
SET y1.someBoolean = 1
WHERE y2.id IS NULL;

外连接技巧是一种查找 y1 的行的方法,该行不存在具有相同 tableZId 和更大 id 的行。换句话说,它为具有给定tableZId 的每组行找到最大的id

【讨论】:

  • 当然,我想看看另一种解决方案
  • 不错。我会修改 UPDATE 语句
  • 注意我没有测试过!请不要在您的真实数据上进行测试。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 2014-06-18
  • 2019-11-04
  • 2016-01-12
  • 1970-01-01
  • 2017-07-31
相关资源
最近更新 更多