我想将参数传递给过程,并在声明游标时将其用作表名。以下代码返回错误消息:#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');
答案 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文本中的文字,就像保留关键字。