使用带游标的准备好的语句 [英] Using prepared statements with cursor
本文介绍了使用带游标的准备好的语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我将游标声明放在准备好的语句中,然后执行它,然后返回一个错误 #1324 - Undefined CURSOR: getid.
我该如何解决这个问题?
<前>分隔符;;如果存在 test2,则删除程序;;创建过程 test2(table_id VARCHAR(25))开始DECLARE done INT DEFAULT FALSE;声明 id INT;声明 id_new INT;声明 stmt1 VARCHAR(1024);声明 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');从@sqltext1 准备 stmt1;执行 stmt1;设置@id_new = 1;打开 getid;将 getid 获取到 id 中;重复SET @sqltext2 := CONCAT('UPDATE ',table_id,' SET entryId = ? WHERE entryId = ?');从@sqltext2 准备 stmt2;执行 stmt2 使用 @new_id, id;SET @id_new = @id_new + 1;将 getid 获取到 id 中;直到完成结束重复;关闭 getid;结尾;;调用 test2('测试'); 解决方案
一些规则:
- 所有声明都必须在一个序列中的一个地方.
- 不能在游标声明中使用变量名.
- 处理程序声明必须在游标声明之后.
- 不能使用局部变量名 (
id
) 作为绑定参数准备好的陈述.您只能使用session
变量(比如@_id
).
为了解决此类问题,您可以采用以下解决方案.
- 使用 SP 的输入参数定义临时表.
- 现在在同一个表上声明游标并使用它.
- 删除创建的临时表.
以下示例应该适用于您的桌子.
分隔符 $$删除过程如果存在 test2$$创建过程 test2( table_id varchar(25) )开始set @temp_query = '如果存在临时表,则删除临时表 temp_cursor_table';从@temp_query 准备 pst;执行pst;下降准备 pst;- 或者-- 解除分配准备 pst;set @temp_table_query='创建临时表 temp_cursor_table ';set @temp_table_query=concat( @temp_table_query, ' select entryId from ' );设置@temp_table_query=concat(@temp_table_query, table_id);set @temp_table_query=concat( @temp_table_query, ' order by entryId' );从@temp_table_query 准备 pst;执行pst;下降准备 pst;-- 现在编写您的实际游标和更新语句-- 在一个单独的块中开始声明完成 int 默认为假;声明 id 整数;声明 id_new int;声明 stmt1 varchar(1024);声明 stmt2 varchar(1024);声明 getid 游标按 entryId 从 temp_cursor_table order 中选择 entryId;为未找到的集合声明继续处理程序 done = 1;设置@id_new = 1;打开 getid;将 getid 获取到 id 中;重复set @sqltext2 := concat('update', table_id);set @sqltext2 := concat( @sqltext2, ' set entryId = ? where entryId = ?' );设置@_id = id;从@sqltext2 准备 stmt2;使用@new_id、@_id 执行stmt2;设置@id_new = @id_new + 1;将 getid 获取到 id 中;直到完成结束重复;关闭 getid;结尾;结尾;$$分隔符;
现在调用具有 table_id
值的过程.
调用 test2( 'Test' );
I put the cursor declaration in the prepared statement and then executed it, then returns an error #1324 - Undefined CURSOR: getid.
How do I solve this problem?
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');
解决方案
Some rules:
- All declarations must be at one place in a sequence.
- You can't use variable names in cursor declarations.
- Handler declarations must be after cursor declarations.
- You can't use local variable names (
id
) as bound parameters for prepared statements. You can only usesession
variables (say@_id
).
To overcome such problems, you can adopt following solution.
- Define a temporary table using the input parameter to the SP.
- Now declare the cursor on the same table and use it.
- Drop the temporary table created.
Following example should work on your tables.
delimiter $$
drop procedure if exists test2$$
create procedure test2( table_id varchar(25) )
begin
set @temp_query = 'drop temporary table if exists temp_cursor_table';
prepare pst from @temp_query;
execute pst;
drop prepare pst; -- or
-- deallocate prepare pst;
set @temp_table_query='create temporary table temp_cursor_table ';
set @temp_table_query=concat( @temp_table_query, ' select entryId from ' );
set @temp_table_query=concat( @temp_table_query, table_id );
set @temp_table_query=concat( @temp_table_query, ' order by entryId' );
prepare pst from @temp_table_query;
execute pst;
drop prepare pst;
-- now write your actual cursor and update statements
-- in a separate block
begin
declare done int default false;
declare id int;
declare id_new int;
declare stmt1 varchar(1024);
declare stmt2 varchar(1024);
declare getid cursor for
select entryId from temp_cursor_table order by entryId;
declare continue handler for not found set done = 1;
set @id_new = 1;
open getid;
fetch getid into id;
repeat
set @sqltext2 := concat( 'update ', table_id );
set @sqltext2 := concat( @sqltext2, ' set entryId = ? where entryId = ?' );
set @_id = id;
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;
end;
$$
delimiter ;
Now call the procedure with table_id
value.
call test2( 'Test' );
这篇关于使用带游标的准备好的语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文