将光标打开被称为不良做法。但是当你忘记关闭和/或解除分配时会发生什么?它如何影响SQL Server,连接/会话? 使用游标的查询,存储过程和触发器的后果是否有任何差异?
答案 0 :(得分:29)
这取决于您是在本地还是全局声明游标(以及您的环境中的默认值 - 默认为全局,但您可以更改它)。
如果光标是全局的,那么它可以保持" alive"在SQL Server中,直到在创建它的范围内触及最后一段代码。例如,如果您调用创建全局游标的存储过程,然后调用其他20个存储过程,则当其他20个存储过程正在运行时,游标将继续运行,直到调用者超出范围。我相信它会在会话级别保持活跃,而不是连接级别,但还没有彻底测试过。如果光标被声明为local,那么它应该只保留在当前对象的范围内(但同样,这是理论上的,我还没有做过广泛的低级内存测试来确认)。
但是,一般的概念应该是:当你完成某事时,就这样说。
为了使我的游标尽可能高效,我总是使用以下声明:
DECLARE c CURSOR
LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR SELECT ...
我也听说如果你只CLOSE
或DEALLOCATE
,可能会出现内存问题,所以在我完成这项工作时我总是这样做:
CLOSE c;
DEALLOCATE c;
但是,你有多少游标可以清除这种语法?如果你的系统中有数百个游标,那对我来说无疑是一个红旗。
编辑
作为附录,我只想澄清游标本身并不坏。但是,它们经常被误用和滥用 - 在实现更高效,基于集合的解决方案 的情况下实现,但负责编写查询的人只能在程序上进行思考。游标有意义的几个案例:
答案 1 :(得分:6)
不关闭游标会使锁保持活动状态,使其保持在它所在的行上。 即使关闭后,参考仍保留在光标正在使用的数据结构中(因此可以重新打开) 这些结构是特定于SQL服务器的(因此它不仅仅是内存空间或句柄等)并且取决于游标实际执行的操作,但它们通常是临时表或查询结果集。
不解除分配AFAIK只与性能有关。上述资源将保持分配状态,从而对服务器性能产生负面影响。
从(打开或关闭但未解除分配的)游标分配的资源将保持分配,直到会话(或连接)关闭为止
答案 2 :(得分:6)
“不必显式释放游标变量。当变量超出范围时,隐式释放变量。“