2012-10-24 112 views
3

做了一些阅读之后,很明显多个程序可以修改全局变量@@Fetch_Status。我们有一个存储过程,每小时调用一次其他存储过程(类似于一个表驱动的触发器,这样客户端就可以控制,但不需要触摸,只有一个触发器)。所以这个调用这些子程序的父程序使用了一个游标。一些子程序也可以使用游标。我应该避免@@ Fetch_Status?

我知道每个Fetch Next调用几乎紧跟一个@@Fetch_Status电话,但事情并行发生的我不知道,如果调用@@Fetch_Status是线程安全的,特别是考虑到备注部分here。所以,我认为这将是一个好主意,以取代我所有的While @@Fetch_Status = 0)调用能够像

WHILE ((SELECT fetch_status 
FROM sys.dm_exec_cursors(0) 
where name = 'server_cursor')=0) BEGIN 

这在我的电脑上伟大的工作,但是当我把它转移到客户端机器我才知道,我没有选择sys.dm_exec_cursors(0)表中的权限。我收到错误The user does not have permission to perform this action.

或者,如果我尝试select * from sys.syscursors我得到的错误The SELECT permission was denied on the object 'syscursors', database 'mssqlsystemresource', schema 'sys'.

是否有另一种方式做到这一点,以确保多个同时光标在彼此不踩?或者我在这里工作太辛苦了?

+1

'返回当前由连接打开的任何游标所发出的最后一个游标FETCH语句的状态。'因此,如果在调用'FETCH'和检查之间使用游标的'EXEC'语句应该只有一个问题'@@ Fetch_Status'。 –

+0

当然,没有一个过程是这样写的,但procA和procB都使用游标,procA调用下一行,但在它可以检查获取状态procB之前,并行读取最后一行,从而设置全局'@ @ Fetch_Status'为-1。然后,当procA去检查'@@ Fetch_Status'它认为它的行都被提取,但他们不是。或者SQL比这更聪明? – Brad

+1

来自单个连接的程序不会并行运行。可以并行运行的唯一事情就是针对单个查询的并行执行计划。 –

回答

0

解决方法是在您的FETCH NEXT声明之后检查@@FETCH_STATUS。特别是,确保没有可能改变状态的中间呼叫。如有必要,您可以将该值保存到声明的局部变量中。你提到检查状态“几乎立即”。如果你不确定,你最好检查你的代码。

否则,@@FETCH_STATUS应该是可靠的。