【问题标题】:Are cursors ever really the "right" choice?游标真的是“正确”的选择吗?
【发布时间】:2011-11-14 17:23:41
【问题描述】:

在处理数据时,有时过程式编程是绝对无法避免的。

我目前正在优化一些遗留代码。它使用一个游标、63 对IF/ELSE 语句和BEGIN/END 等。我曾希望对游标进行逆向工程并使其成为一个程序过程。现在我已经完成了对算法的解码,我意识到了。 . .哎呀...它必须是程序性的,因为对记录所做的每个选择都取决于对所有先前记录的过程的结果。

所以现在我被撕裂了...还有其他选择可以将过程代码与 SQL Server 处理(CLR SP、UDF 等)混合。我非常相信使用正确的工具来完成这项工作,所以我倾向于为此制作一个 .NET CLR SP。但是稍微简化一下光标会更快,更“容易”,但仍然保留光标。

大家觉得呢?既然我们可以通过 SQL Server 访问 .NET 模块,那么使用游标是否合适(在我看来,这从一开始就是一个杂项/工作)。

【问题讨论】:

    标签: sql-server sqlclr procedural-programming set-based


    【解决方案1】:

    至少对于 SQL Server,它同时具有会话和全局临时表和表变量,我无法想象我会选择使用服务器端游标的场景。正如您在旧版应用程序中发现的那样,并非所有代码都可以基于集合(您确定没有其他选择吗?),但即使您必须按程序遍历记录,游标也是最糟糕的选择。

    使用表变量,例如, (对于非常大的表集,这种方法开始降低性能)

     Declare @Pks Table (pk integer primary key not null)
     Insert @pks(pk)
     Select pkcolName from table where ... [here put logic to 
               extract id values for rows you need to iterate over
    
     -- then put procedural code here ...
     Declare @pk Integer
     While Exists (Select * From @pks) Begin
         Select @pk = Max(pk) From @pks -- assuming you need to work 
                                 -- on pk values from highest to lowest
         // Here do work on one record at a time, using value in @pk
         Delete @pks Where pk = @pk
     End
    

    【讨论】:

    • 除了游标之外,你会推荐什么程序迭代?不,这必须是程序性的。我想了很多,把它拆散了,没有办法做到基于集合。
    • 我不完全确定,但我认为唯一可以比较有利的游标类型是向前看的只读游标,可以说,它根本不是服务器端游标,而只是一种语法表示上面的代码做了什么......没有直接给你的控制。
    【解决方案2】:

    我会在客户端/应用服务器上用 C# 运行一个循环,根据需要调用存储过程。通常,C# 的开发和单元测试速度更快、更容易,而且它比存储过程运行得更快,即使您使用 CLR,它也会在数据库中完成所有操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 2021-11-06
      • 2010-11-20
      相关资源
      最近更新 更多