光标提取返回Null

时间:2016-06-28 12:43:27

标签: mysql loops stored-procedures cursor

问题很明显,但我已经尝试了很多东西来修复它,包括使用不同的变量名而不是表字段。从游标获取的值始终返回null。分配给游标提取的值是相同的数据类型(int(11))。我正在做的是将游标的select_id值从游标的select表中分配到@my_key_id int(11)变量中,但它一直保持为null。

        declare my_key_id int(11); /*variable that will be assigned from the     value in cursor*/
        DECLARE done INT DEFAULT FALSE; /*for cursor break*/

        DECLARE cr_cursor cursor for select key_id from tmp_valuesss;     /*cursor declaration*/
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; /*break     thingy*/

        open cr_cursor;

        read_loop: LOOP

            IF done THEN
                LEAVE read_loop;
            END IF;

            select @my_key_id;

            FETCH cr_cursor INTO my_key_id;
        END LOOP;

        close cr_cursor;

1 个答案:

答案 0 :(得分:4)

您误将用户变量(带有@符号的用户变量)与局部变量(带有DECLARE的用户变量)混淆。

您的用户变量从未设置过,因此始终为空。

此外,DEALLOCATE任何PREPARE var。

Fetch向上移动到LOOP开头。

drop procedure if exists calculate_thingy;
delimiter $$
CREATE PROCEDURE calculate_thingy
(
    IN table_name VARCHAR(100)
)
BEGIN
    DECLARE SQL_STATEMENT NVARCHAR(8000);

    drop table if exists tmp_valuesss;

    SET @SQL_STATEMENT = CONCAT('CREATE TABLE IF NOT EXISTS tmp_valuesss AS     (SELECT * FROM ', table_name, ')');    
    PREPARE STMT FROM @SQL_STATEMENT;
    EXECUTE STMT;
    DEALLOCATE PREPARE STMT; -- Drew added -------------------

    alter table tmp_valuesss add the_field float;

    begin
        declare my_key_id int(11); /*variable that will be assigned from the     value in cursor*/
        DECLARE done INT DEFAULT FALSE; /*for cursor break*/

        DECLARE cr_cursor cursor for select key_id from tmp_valuesss;     /*cursor declaration*/
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; /*break     thingy*/

        open cr_cursor;

        read_loop: LOOP
            FETCH cr_cursor INTO my_key_id;
            IF done THEN
                LEAVE read_loop;
            END IF;
            select my_key_id;
        END LOOP;
        close cr_cursor;
    end;
END $$
DELIMITER ;

有几点需要注意。首先,上面介绍整个块的原因是为了帮助未来的访问者,因为许多人都在努力解决DELIMITER问题,因此创建存储过程可能会遇到问题。此外,开头的下降对于第二次及之后对proc的编辑很重要。

此外,这显然只是测试您提供的概念存储过程。这意味着,通过在LOOP中执行select my_key_id;,您实际上在消费者端创建了一个额外的结果集(使用call语句调用存储过程)。您是否有能力处理代码中的多个结果集将影响您对此的审核。

此外,它由您作为参数传递的表名的状态驱动。因此,如果该表包含值或空值,则可以根据代码和传递该表名的决定获得所获得的值。据称包含列key_id的表,因为这是您开始编写存储过程的方式。

下面的视图是有效的,有多个结果集。

enter image description here

上面的图片显示了一张桌子,里面有两排鱼和青蛙。返回了两个结果集(这就是你编码的方式)。我突出显示了第二个结果集,它显示了从它返回的值(它是id 2)...在LOOP结束之前发生的最后一行。

我建议您第三次尝试编辑此答案,而不是尝试在我的问题中根据我在评论中提供的链接与我聊天。