sql-server – 使用游标的优点和缺点(在SQL服务器中)

在这里问了一个问题 Using cursor in OLTP databases (SQL server)

人们回应说,不应该使用游标.

我觉得游标是非常强大的工具,意味着要使用(我不认为Microsoft支持错误的开发人员的游标).假设你有一个表,其中一行中的列的值取决于同一列的值在上一行.如果是一次性后端进程,您认为使用游标是否是可接受的选择?

在我的脑海中,我可以想到几个场景,我觉得使用游标不应该感到羞耻.如果你们有其他的感觉,请告诉我.

1>一次性后端处理,用于清除在几分钟内完成执行的坏数据.
2>在很长一段时间内运行一次的批处理(类似于一年一次).
如果在上述场景中,其他过程没有明显的压力,那么花费额外的时间编写代码以避免使用游标是不合理的?换句话说,在某些情况下,开发人员的时间比对其他任何事物几乎没有影响的流程的执行更重要.

在我看来,这些是你应该认真尝试避免使用游标的一些场景.
1>从网站调用的存储过程可以经常被调用.
2>每天运行多次并消耗大量资源的sql作业.

我认为在不分析手头的任务并实际权衡其他选择的情况下,做出像“游标不应该被使用”这样的一般性陈述是非常肤浅的.

请告诉我你的想法.

解决方法

有几种情况下游标实际上比基于集合的等价物更好.总是会想到运行总计 – 寻找Itzik的话(并忽略任何涉及sql Server 2012的内容,它增加了新的窗口函数,在这种情况下为游标提供了运行).

人们对游标的一个重大问题是它们执行缓慢,它们使用临时存储等.这部分是因为认语法是具有各种低效认选项的全局游标.下次你用光标做一些事情,不需要做一些事情,比如UPDATE … WHERE CURRENT OF(我已经能够避免我的整个职业生涯),通过比较这两个来给它一个公平的动摇语法选项:

DECLARE c CURSOR 
    FOR <SELECT QUERY>;

DECLARE c CURSOR 
    LOCAL STATIC READ_ONLY FORWARD_ONLY
    FOR <SELECT QUERY>;

实际上,第一个版本表示未记录的存储过程sp_MSforeachdb中的错误,如果任何数据库的状态在执行期间发生更改,则会使其跳过数据库.我随后编写了我自己的存储过程版本(参见herehere),它们都修复了错误(只需使用上面语法的后一版本)并添加了几个参数来控制选择哪些数据库.

很多人认为方法不是游标,因为它没有说DECLARE CURSOR.我见过有人认为while循环比游标更快(which I hope I’ve dispelled here)或者使用FOR XML PATH执行组连接并不执行隐藏游标操作.在很多案例中查看计划将显示真相.

在很多情况下,使用基于集合的游标更合适.但是有很多有效的用例,其中基于集合的等价物编写要复杂得多,优化器可以为两者或两者生成计划(例如,在循环表中更新统计信息的维护任务,为结果中的每个值调用存储过程,等等.对于许多大型多表查询也是如此,其中计划对于优化器来说太过怪异.在这些情况下,最好先将一些中间结果转储到临时结构中.对于游标的某些基于集合的等价物(如运行总计)也是如此.我还写过另一种方式,人们几乎总是本能地想到使用while循环/光标而且有clever set-based alternatives that are much better.

更新2013-07-25

只是想添加一些关于游标的其他博客文章,如果你必须使用它们应该使用哪些选项,并使用基于集合的查询而不是循环来生成集合:

Best Approaches for Running Totals – Updated for SQL Server 2012

What impact can different cursor options have?

生成没有循环的集合或序列:[Part 1] [Part 2] [Part 3]

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...