首页 文章

声明游标时使用变量

提问于
浏览
2

我想将参数传递给过程,并在声明游标时将其用于表名 . 以下代码返回错误消息:#1146 - 表'db.table_id'不存在 .

声明游标时如何使用参数?

谢谢

delimiter ;;

drop procedure if exists reset_id;;

create procedure reset_id(table_id VARCHAR(25))
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE id INT;
    DECLARE id_new INT;
    DECLARE getid CURSOR FOR SELECT entryId FROM table_id ORDER BY entryId;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    SET @id_new = 1; 

    OPEN getid;

    FETCH getid into id;
    REPEAT
        UPDATE table_id SET entryId = @id_new WHERE entryId = id;
        SET @id_new = @id_new + 1;
        FETCH getid into id;
    UNTIL done END REPEAT;
    CLOSE getid;
END
;;

CALL reset_id('Test');

修改过程后,仍然会返回错误#1324 - Undefined CURSOR:getid . 我该如何解决这个问题?

delimiter ;;

drop procedure if exists test2;;

create procedure test2(table_id VARCHAR(25))
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE id INT;
    DECLARE id_new INT;
    DECLARE stmt1 VARCHAR(1024);
    DECLARE stmt2 VARCHAR(1024);
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    SET @sqltext1 := CONCAT('DECLARE getid CURSOR FOR SELECT entryId FROM ',table_id,' ORDER BY entryId');
    PREPARE stmt1 FROM @sqltext1;
    EXECUTE stmt1;

    SET @id_new = 1; 

    OPEN getid;

    FETCH getid into id;
    REPEAT
        SET @sqltext2 := CONCAT('UPDATE ',table_id,' SET entryId = ? WHERE entryId = ?');
        PREPARE stmt2 FROM @sqltext2;
        EXECUTE stmt2 USING @new_id, id;
        SET @id_new = @id_new + 1;
        FETCH getid into id;
    UNTIL done END REPEAT;
    CLOSE getid;
END
;;

CALL test2('Test');

1 回答

  • 0

    必须在SQL文本中指定表名;它不能是一个变量 .

    要完成您要执行的操作,您将需要动态创建包含要执行的SQL文本的字符串 .

    从任意字符串准备语句:

    SET @sqltext := CONCAT('UPDATE ',table_id,' SET entryId = ? WHERE entryId = ?');
    PREPARE stmt FROM @sqltext;
    

    请注意, table_id 值将合并到字符串变量中,然后 PREPARE 语句(基本上)将该字符串转换为实际的SQL语句 .

    要执行准备好的语句并为绑定变量提供值,您可以执行以下操作:

    EXECUTE stmt USING @new_id, @id;
    

    您可以多次重新执行预准备语句,而无需再次准备 . 因此,PREPARE将在循环之前完成,EXECUTE可以在循环内完成 .

    完成语句后,在循环之后,最佳做法是释放语句,如下所示:

    DEALLOCATE PREPARE stmt;
    

    NOTE:

    关于表名不是变量的限制实际上适用于SQL语句中的所有标识符,包括表,视图,列,函数等的名称 . 这些都必须是SQL文本中的文字,就像保留的关键字一样 .

相关问题