【问题标题】:MySQL Cursor fetching only one rowMySQL游标只获取一行
【发布时间】:2012-08-18 10:38:45
【问题描述】:

我的 SQL:

CREATE PROCEDURE INV_MIN_PURCHASE_PRICE()
BEGIN
DECLARE done INT;
DECLARE current_inventory_ID INT;
DECLARE cur1 CURSOR FOR SELECT inventory_ID FROM _inventory;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

SET done = 0;
OPEN cur1;

REPEAT

    FETCH cur1 INTO current_inventory_ID;
    UPDATE _debug SET rows=rows+1;

UNTIL done
END REPEAT;

CLOSE cur1;

END;

当我调用此过程时,MySQL 仅获取一行(_debug rows 增加 1)。为什么??是bug吗?

【问题讨论】:

    标签: mysql sql database-cursor


    【解决方案1】:

    我刚刚在 MySQL 中的存储过程遇到了同样的问题。它应该从一个表中获取某个列中具有空值的所有记录,然后从另一个表中填充该值。但是,它在一个记录后停止:

    CREATE PROCEDURE `updateRecord`()
        BEGIN
    
        DECLARE done INT DEFAULT FALSE;
        DECLARE recordId, newValue INT;
        DECLARE current_record CURSOR FOR SELECT id FROM A where b_id is null;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
    
        OPEN current_record;
    
        main_loop: LOOP
            FETCH current_record INTO recordId;
    
            IF done THEN
                 LEAVE main_loop;
            END IF;
    
            -- fetching some value from table b
            select id into newValue from B where ...
    
           -- setting new value in record
           update A set b_id = newValue where id = recordId;    
    
          END LOOP;
        END
    

    答案是“未找到的处理程序”不仅在游标没有返回行时执行,而且在表 B 上的选择没有返回行时执行。我的解决方案是使用由处理程序设置的第二个变量,并在选择后重置“完成”变量:

        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE, noBfound = TRUE;    
    
               [...]
    
               select id into newValue from B where ...
    
               IF (noBfound = TRUE) THEN 
                   SET done = FALSE;
               END IF;
    
               [...]
    

    补充:通过简单地在选择后重置“完成”显然可以不使用第二个变量:

        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
    
               [...]
    
               select id into newValue from B where ...
    
               SET done = FALSE;
    
               [...]
    

    【讨论】:

    • 这是正确的做法:补充:很明显可以通过简单地在选择后重置“完成”来避免第二个变量。干净简洁
    【解决方案2】:

    您是否尝试过 LOOP 而不是 REPEAT 构造?似乎在 MySQL 中工作得更好。将 REPEAT to END REPEAT 部分替换为:

    inv_loop: LOOP
        FETCH cur1 INTO current_inventory_ID;
        IF done = 1 THEN
            LEAVE inv_loop;
        END IF;
        UPDATE _debug SET rows=rows+1;
    END LOOP;
    

    【讨论】:

    • 我首先尝试了这个(基于 MySQL 文档中的示例)。没有成功。
    • 我假设如果你只是在 MySQL 控制台中尝试 SELECT inventory_id FROM _inventory 你会得到不止一行,对吧?
    • 当然。我已经解决了这个问题。将我的 MySQL 服务器更新到最新版本,现在代码可以正常工作了。
    【解决方案3】:
    IF done THEN
             LEAVE main_loop;
    ELSE
             ITERATE main_loop;
    END IF;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多