【问题标题】:Cursor Fetch Returns Null游标获取返回 Null
【发布时间】:2016-10-30 19:18:24
【问题描述】:

问题很清楚,但我已经尝试了很多方法来解决它,包括使用与表字段不同的变量名。从游标中获取的值总是返回 null。分配给游标提取的值是相同的数据类型 (int(11))。我正在做的是将从游标的选择表中提取的 key_id 值分配给 @my_key_id int(11) 变量,但它一直为空。

        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;

【问题讨论】:

  • 如果 Drew 的帖子回答了您的问题,您应该接受答案,而不是删除您的问题。
  • 我的错误,不是要删除的意思。
  • @MeinHat 如果您在存储过程中遇到问题或相关问题,请随时在Campaigns 房间与我聊天,我们可以解决。
  • 如果您有其他问题,最好ask a new question 而不是继续编辑这个问题。

标签: mysql loops stored-procedures cursor


【解决方案1】:

您将用户变量(带有@ 符号的变量)误认为是局部变量(带有 DECLARE 的变量)。

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

另外,DEALLOCATE 任何 PREPARE 变量。

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 编辑很重要。

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

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

下面的视图是它的工作,有多个结果集。

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

我建议您不要第三次尝试编辑此答案,而是通过我在您问题下方的评论中提供的链接加入我的聊天。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-01
    • 2019-04-18
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2018-02-26
    • 1970-01-01
    相关资源
    最近更新 更多