简体   繁体   English

SQL Server:在不使用游标的情况下为每一行调用具有副作用的存储过程

[英]SQL Server : call stored procedure with side effects for each row without using a cursor

Before you say this is identical to SQL Call Stored Procedure for each Row without using a cursor let me clarify my question: 在您说这与每行的SQL调用存储过程相同( 不使用光标)之前,让我澄清一下我的问题:

The stored procedure does have side effects. 该存储过程确实有副作用。 In fact, it's all about those side effects, as the results of each call influence further processing. 实际上,这完全与那些副作用有关,因为每个调用的结果都会影响进一步的处理。

Think of it like this: the table contains rule definitions, and the proc executes those rules literally RBAR, making changes to another table. 可以这样认为:该表包含规则定义,而proc按字面意义执行RBAR规则,从而对另一个表进行更改。

Under those conditions I do not see how a set operation is possible, CROSS APPLY probably can't be used because of side effects, but it's also not needed, since I'm not really joining the rule table with any results. 在这种情况下,我看不到如何进行设置操作,可能由于副作用而不能使用CROSS APPLY,但是也不需要使用CROSS APPLY,因为我并没有真正加入任何结果的规则表。

If the solution is really RBAR, should I still try to avoid using CURSOR? 如果解决方案确实是RBAR,我是否仍应尝试避免使用CURSOR? Is using WHILE with READ TOP 1 WHERE Key > @Key a better solution? 使用WHILE和READ TOP 1 WHERE Key> @Key是更好的解决方案吗? Why? 为什么?

The more I searched, the more I came to the conclusion that fast_forward read_only cursor is the simplest and fastest solution. 搜索的次数越多,得出的结论越多,即fast_forward read_only游标是最简单,最快的解决方案。

cursors are inherently bad 游标本来就不好

No. Cursors are easily misused, and tend to be leapt upon by people new to SQL because they're from a procedural background and haven't even heard of "set-based". 不能。游标很容易被滥用,并且SQL的新手往往会喜欢它,因为他们来自程序背景,甚至还没有听说过“基于集合的”。 Cursors have their place, and if you've assessed the available approaches and concluded that cursors are a good fit, I'd say use one. 游标有其位置,如果您评估了可用的方法并得出结论,游标是一个很好的选择,我会说一个。

Using a WHILE loop to hide the fact that what you're really doing is using a cursor is also something I'd recommend against. 我还建议您使用WHILE循环隐藏您实际上在使用游标的事实。

One final note - you mentioned fast_forward and read_only - but one other recommendation would be local - that way, if something goes wrong, at least the cursor is cleaned up when you exit whatever scope your cursor is running in - rather than persisting for the lifetime of the connection. 最后一点-您提到了fast_forwardread_only但另一条建议是local -这样,如果出现问题,至少在退出运行游标的范围时清理游标-而不是永久保存连接的。

        --- create one temp table using temprory talbe
        declare @test_Table  table (id int, num int, name varchar(50))
        --- fetch all data from your table to temp talbe
        insert into @test_Table (id,num,name)
        select id,number,name from TESTNUMBERS

        ----select * from TESTNUMBERS

        declare @count int
        declare @id int
        set @count=(select COUNT(1) from @test_Table)
        --- create while loop to work on particular row 
        while (@count <>0)
        begin
        set id=(select top 1 id from @test_Table)
        ---- do you task wiht that row and call your stored procedure on this row
        ---then delete that row form temp table variable 
        delete from @test_Table where id=@id
        --- decarease count to maintain loop 
        set @count=@count-1
        end

you can use this type of loop to work on each row without using cursor. 您可以使用这种类型的循环在每一行上工作而无需使用光标。

steps : 脚步 :

  1. stoere data in temprory teble 在临时菜单中存储数据

  2. get count of all rows 获取所有行的计数

  3. in loop fetch top 1 row from temp table 循环从临时表中获取顶部1行

  4. do all your task in on that row 在该行中完成所有任务

  5. den delete that row from temp table den从临时表中删除该行

  6. decrement count by 1 递减计数1

6 if it helps then enjoy..... 6如果有帮助,然后享受.....

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM