【问题标题】:MySql Fetch cursor into variable return nullMySql 获取游标到变量中返回 null
【发布时间】:2016-02-04 14:40:42
【问题描述】:

问题在于 FETCH INTO(在循环中)没有将值放入变量中。我查看了MYSQL | SP | CURSOR - Fetch cursor into variable return null,但该表已被填充。

事务表如下所示:

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

存储过程:

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

运行存储过程会返回这个结果:

+--------------------------+
|CONCAT("Count: ", counter)|
+--------------------------+
|                  Count: 1|
+--------------------------+

调试表中的结果是:

+------------+---------+-----------------------+
|iddebugTable|bigintval|                 strval|
+------------+---------+-----------------------+
|           1|     NULL|"transactionId is NULL"|
+------------+---------+-----------------------+

这意味着该值没有被复制

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

+-------------+
|transactionid|
+-------------+
|          591|
+-------------+

【问题讨论】:

    标签: mysql stored-procedures


    【解决方案1】:

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

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

    收件人:

    DECLARE txnEntryCur CURSOR FOR 
        SELECT 
            `transactionentry`.`transactionid`
        FROM 
            `transactionentry`
        LIMIT 1;
    

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

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

    我希望这可以为将来节省一些时间。

    【讨论】:

    • 我使用table.field 解决了我的问题,而不是仅使用字段名称。谢谢!
    • 多么愚蠢的错误。花了一个小时来解决这个问题,直到找到你的帖子......谢谢!
    • 非常感谢分享这个。在这个原本阳光明媚的星期天早上,奇怪的错误测试了我一段时间的理智,我本来应该做一些更有趣的事情。
    • 这个错误也出现在 MariaDB 10.6.4 上。如果我没有到达你的帖子,我会花一整天谢谢你!
    【解决方案2】:

    你的问题在这里:

    DECLARE transactionId BIGINT(20);
    

    您声明了一个名为 transactionId 的变量,所以当您这样做时:

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

    您的光标选择选择了您声明的变量,这就是完全限定字段有效的原因。但是,如果您不想完全限定您选择中的字段,您可以重命名您的变量。

    【讨论】:

      【解决方案3】:

      尝试给变量transactionId一个默认值

      ...
      DECLARE transactionId BIGINT(20) DEFAULT 0
      ...
      

      也替换

      DECLARE noEntries INTEGER DEFAULT FALSE;
      

      DECLARE noEntries BOOLEAN DEFAULT FALSE;
      

      因为您想将其用作BOOLEAN 值并在稍后的过程中将其设置为TRUE

      【讨论】:

      • 感谢您的回复。不,没有用,调试表中的条目现在是 0(不是 NULL),但不是 select 语句返回的值,即 591。 noEntries 是一个布尔值,但在所有调整中,它最终变成了一个INT,即使修复也无济于事。
      猜你喜欢
      • 2016-10-30
      • 2017-04-01
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      • 2015-02-25
      • 1970-01-01
      • 2014-04-18
      • 1970-01-01
      相关资源
      最近更新 更多