MySql将游标提取到变量中返回null

Tun*_*enX 1 mysql stored-procedures

问题是FETCH INTO(在循环中)没有将值放入变量中.我看过MYSQL | SP | CURSOR - 将游标提取到变量返回null 但该表已经填充.

事务表如下所示:

CREATE TABLE `transactionentry` (
    `transactionid` bigint(20) NOT NULL AUTO_INCREMENT,
    ...
    PRIMARY KEY (`transactionid`),
    ...
) ENGINE=InnoDB AUTO_INCREMENT=651 DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)

存储过程:

PROCEDURE `doTxnHouseKeeping`()
BEGIN
    -- Loop invariant
    DECLARE noEntries INTEGER DEFAULT FALSE;
    -- Error codes
    DECLARE code CHAR(5) DEFAULT '00000';
    DECLARE msg TEXT;
    -- Txn vars
    DECLARE transactionId BIGINT(20);
    DECLARE lastTransactionId BIGINT(20) DEFAULT 0;
    -- testing
    DECLARE counter INT(11) DEFAULT 0;

    DEClARE txnEntryCur CURSOR FOR 
        SELECT 
            `transactionid`
        FROM 
            `transactionentry`
        LIMIT 1;

    DECLARE CONTINUE HANDLER FOR 
        NOT FOUND SET noEntries = TRUE;  

    DECLARE EXIT HANDLER FOR
        SQLEXCEPTION
            BEGIN
                GET DIAGNOSTICS CONDITION 1
                code = RETURNED_SQLSTATE, msg = MESSAGE_TEXT;
                SELECT CONCAT('Error fetching transaction entries code: ', code, ' message: ', msg);
            END;

    OPEN txnEntryCur;

    mainLoop: LOOP
        FETCH 
            txnEntryCur 
        INTO 
            transactionId;

        IF noEntries THEN 
            LEAVE  mainLoop;
        END  IF;

        IF transactionId IS NOT NULL THEN
            INSERT INTO debugTable (`bigintval`) VALUES (transactionId);
        ELSE
            INSERT INTO debugTable (`strval`) VALUES ('transactionId is NULL');
        END IF;

        SET counter = counter + 1;
    END LOOP mainLoop;

    CLOSE txnEntryCur;

    SELECT CONCAT("Count: ", counter);        
END
Run Code Online (Sandbox Code Playgroud)

运行存储过程将返回以下结果:

+--------------------------+
|CONCAT("Count: ", counter)|
+--------------------------+
|                  Count: 1|
+--------------------------+
Run Code Online (Sandbox Code Playgroud)

调试表中的结果是:

+------------+---------+-----------------------+
|iddebugTable|bigintval|                 strval|
+------------+---------+-----------------------+
|           1|     NULL|"transactionId is NULL"|
+------------+---------+-----------------------+
Run Code Online (Sandbox Code Playgroud)

这意味着该值未被复制

运行SQL时(就像在存储过程中一样),它返回:

+-------------+
|transactionid|
+-------------+
|          591|
+-------------+
Run Code Online (Sandbox Code Playgroud)

Tun*_*enX 8

我发现了问题,这很奇怪.它不会导致任何错误和/或异常,只是不会将任何值放入变量中.解决方案是从以下位置更改游标声明语句:

DECLARE txnEntryCur CURSOR FOR 
    SELECT 
        `transactionid`
    FROM 
        `transactionentry`
    LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

至:

DECLARE txnEntryCur CURSOR FOR 
    SELECT 
        `transactionentry`.`transactionid`
    FROM 
        `transactionentry`
    LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

甚至文档都没有表明它可能是一个问题(https://dev.mysql.com/doc/refman/5.7/en/declare-cursor.html)

如果我从多个表中进行选择,那么我只完全限定SQL语句的SELECT(和WHERE)部分,因此从未在更复杂的查询中选择它.

我希望这将在未来节省一些时间.

  • 我使用 `table.field` 而不是字段名称解决了我的问题。谢谢 ! (2认同)