声明游标时使用变量

时间:2014-02-08 19:58:23

标签: mysql sql phpmyadmin

我想将参数传递给过程,并在声明游标时将其用作表名。以下代码返回错误消息:#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 - 未定义的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 :(得分: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;

注意:

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