执行动态游标失败的问题

存储过程中使用了动态游标,程序片断如下
exec('declare cur cursor for select * from table '+ @where);
open cur;
fetch next from cur into @v1,@v2
语法上没什么问题,原来也都是运行正常,正在进行功能测试着呢。突然从昨天看是提示:
服务器: 消息 16916,级别 16,状态 1,过程 Query,行 231
A cursor with the name 'cur' does not exist.
什么原因导致的?
---------------------------------------------------------------

估计没有比重建更好的方法了?
---------------------------------------------------------------

是不是其他地方的错误,比如游标关闭后再使用的。
你确定行 231就是在这一段吗?

---------------------------------------------------------------

@where变量的值可能有问题!
造成exec语句执行失败,动态定义光标失败。
因此server上会报这个错误。

请仔细检测你的@where变量,将其打印出来看看是否是标准的。

---------------------------------------------------------------

单步跟踪看看呢

---------------------------------------------------------------

cur写在字符串中,用open可以吗?

exec('declare cur cursor for select * from table '+ @where);
exec('open cur');
exec('fetch next from cur into '+@v1'+','+@v2)
试试

---------------------------------------------------------------

铁斑竹说的可能性最大!

---------------------------------------------------------------

IronPromises(铁诺) 说的最有可能
---------------------------------------------------------------

对..
同意..
应该是条件子句有问题..
---------------------------------------------------------------

exec('declare cur cursor for select * from table '+ @where)中的表名叫table吗?
declare str varchar(200)
str='declare cur cursor for select * from table '+ @where
select str
看看输出的结果是否合理
---------------------------------------------------------------

单步跟踪,看条件语句是否正确!!根据你说的,也只能给出此结论了!!
---------------------------------------------------------------

不瞒你说,我在一年前的这个时候首次使用动态光标的时候就出现过这种问题。
我有一个表TransMaster,里面有个varchar型的字段COMP_ID,这个字段有可能存放’001’之类的全数字varchar型字符,也有可能存放’ABC’之类的有字母的varchar型字符。

那么我如果我这样写的静态SQL的话:
declare @comp_id varchar(3)
set @comp_id = '001'
select TRANS_NO from TransMaster where COMP_ID = @comp_id
或者
declare @comp_id varchar(3)
set @comp_id = 'ABC'
select TRANS_NO from TransMaster where COMP_ID = @comp_id
怎么样都不会报错。

但是我如果要改成动态光标性质的话:
declare @comp_id varchar(3),@SQL varchar(4000)
set @comp_id = '001'
set @SQL = 'select TRANS_NO from TransMaster where COMP_ID = '+ @comp_id
exec ('declare cur cursor for '+@SQL)
open cur
……
这样也不会报错。但是我要是把第二句set @comp_id = '001'改成set @comp_id = 'ABC'的话就会报出和你现在一模一样的错误,说光标cur不存在!!
后来我知道了原因,就引入了QUOTENAME函数,将第三句
set @SQL = 'select TRANS_NO from TransMaster where COMP_ID = '+ @comp_id
改成了:
set @SQL = 'select TRANS_NO from TransMaster where COMP_ID = '+QUOTENAME(@comp_id,'''')
然后无论什么情况都不会出错了。

至于为什么会这样,我想海阔天空兄和一剑飘香兄等人肯定都知道。
如果你现在不知道,那么也不要紧,经验总是要慢慢积累的嘛!

像上面很多人写的单步跟踪什么的就不要去管他们了,简直是浪费时间!
你只要你的@where这个变量print出来告诉我,然后将你的table的字段类型告诉我就OK了。我帮你搞定。

---------------------------------------------------------------

其实关键的原因就在于:
如果TransMaster表的COMP_ID是字符型的话
select TRANS_NO from TransMaster where COMP_ID = 001
这条语句不会出错,只是找不到纪录。因为有个隐式转换在里面。

select TRANS_NO from TransMaster where COMP_ID = ABC
这条语句就会报错。

---------------------------------------------------------------

我覺得原因可能有三個。
1、鐵斑竹說的
2、有可能default to local cursor 的默認值發生了改變。在不指定local/global的情況下,默認是global的。2000下可用
SELECT DATABASEPROPERTYEX('northwind','IsLocalCursorsDefault')去查是否為1。 也可用EXEC sp_dboption去查default to local cursor 的值是否為true.
3、由於是global 的,所以其它進程可能已經關掉這個cursor了,所以沒辦法看見。

---------------------------------------------------------------

呀,我忽略了飘香的第3点。
光标的缺省值是global的。
有可能其它的session将其关闭了。

Published At
Categories with 数据库类
Tagged with
comments powered by Disqus