【问题标题】:stored procedure broke in release mySQL 8.0.22存储过程在 mySQL 8.0.22 版本中中断
【发布时间】:2020-11-12 14:52:46
【问题描述】:

随着mySQL 8.0.22的发布,这个存储过程

    CREATE DEFINER=`workbench`@`%` PROCEDURE `loopPIDCreate`( IN startPID VARCHAR(4) , IN i INTEGER)
    
    SET @cpid = startPID
    
    WHILE ( i > 0 ) DO
    
                SET @PPPX = (SELECT MID(@cpid,4,1));
    
                SET @NNNX = (SELECT `Next` FROM `f930_nonsalespidsequence` WHERE `Current` = @PPPX);
    
                ....[other processing ]
    
                SET @newpid = (SELECT CONCAT(@XNNN,@NXNN,@NNXN,@NNNX));
    
                INSERT INTO `e1p1`.`f940_newpidtable` (SELECT @newpid);
    
                SET cpid = newpid;
                            
            END WHILE;
     END

将在第一次通过后停止更新值(i 在其第二次和后续通过时,因为它向 0 递减)。

引用 A Mighty Wind 中的 Fred Willard 的话,“嘿,发生了什么事?”

【问题讨论】:

  • 使用SELECT .. INTO variable FROM .. 而不是SET variable = (SELECT ..
  • 谢谢秋名。在这种情况下,将这些变量保留在会话范围之外会更干净,因此我将坚持使用 DECLARE 修复,如下面的答案中所述。但是如果我需要更新一个我想在整个会话中可用的变量,很高兴了解 SELECT...INTO

标签: mysql stored-procedures session-variables local-variables


【解决方案1】:

这是optimizations introduced in mySQL 8.0.22 的直接结果。特别是,“存储过程中的语句现在也只准备一次”显然也适用于会话变量。它们只被初始化和评估一次,并且在随后的每个迭代中它们都是空的(或未定义的)。更新和工作版本如下所示:

BEGIN
        DECLARE PPPX CHAR(4);       -- 20201112 New Optimization 8.0.22 requires local instead of session (@var) variables
        DECLARE PPXP CHAR(4);
        DECLARE PXPP CHAR(4);
        DECLARE XPPP CHAR(4);

        [...other processing]

       SET NNNX = (SELECT `Next` FROM `f930_nonsalespidsequence` WHERE `Current` = PPPX);  

-- note the loss of '@', from session to local with matching DECLARE up top

解决方法是在存储过程中正确使用DECLARE-ed 局部变量。有了更多的经验,我会避免这种错误。会话变量在存储过程中工作,但从未打算成为局部变量。 mySQL 优化器终于在这个最新版本中赶上了这一事实。

A short and useful reference on local variables in stored procedures is here.

【讨论】:

    猜你喜欢
    • 2017-01-29
    • 1970-01-01
    • 2021-04-07
    • 2018-09-01
    • 1970-01-01
    • 2012-03-17
    • 2012-06-15
    • 2010-10-12
    • 1970-01-01
    相关资源
    最近更新 更多