如何为查询返回的每一行执行一次存储过程?

我有一个存储过程以某种方式改变用户数据。 我把它传递给user_id,这是它的事情。 我想在一个表上运行一个查询,然后为每个user_id我find运行存储过程一次user_id

我将如何写这个查询?

使用游标

附录:[MS SQL游标示例]

declare @field1 int declare @field2 int declare cur CURSOR LOCAL for select field1, field2 from sometable where someotherfield is null open cur fetch next from cur into @field1, @field2 while @@FETCH_STATUS = 0 BEGIN --execute your sproc on each row exec uspYourSproc @field1, @field2 fetch next from cur into @field1, @field2 END close cur deallocate cur 

在MS SQL中, 这里是一个示例文章

注意游标比基于集合的操作慢,但比手动while循环更快; 在这个SO问题中的更多细节

附录2:如果您要处理的不仅仅是几条logging,请先将它们拖到临时表中,然后将光标移到临时表上; 这将防止SQL升级到表锁并加速操作

附录3:当然,如果您可以内联任何存储过程对每个用户标识进行操作,并将整个事件作为单个SQL更新语句运行,那么这将是最佳的

尝试改变你的方法,如果你需要循环!

在父存储过程中,创build一个包含您需要处理的数据的#temp表。 调用子存储过程,#temp表将是可见的,你可以处理它,希望使用整个数据集,没有光标或循环。

这真的取决于这个子存储过程正在做什么。 如果你正在更新,你可以“更新”join#temp表,并在一个语句中做所有的工作,没有循环。 对于INSERT和DELETE也可以做同样的事情。 如果您需要使用IF进行多个更新,则可以使用#temp表将其转换为多个UPDATE FROM ,并使用CASE语句或WHERE条件。

在数据库中工作时,试图失去循环的心态,这是一个真正的性能消耗,将导致locking/阻塞,并减缓处理速度。 如果你到处循环,你的系统将不能很好地扩展,当用户开始抱怨缓慢的刷新时,加速很难。

发布你想要循环调用的这个过程的内容,我打赌10次中有9次,你可以把它写成一组行。

你的表格和字段名称将需要这样的replace。

 Declare @TableUsers Table (User_ID, MyRowCount Int Identity(1,1) Declare @i Int, @MaxI Int, @UserID nVarchar(50) Insert into @TableUser Select User_ID From Users Where (My Criteria) Select @MaxI = @@RowCount, @i = 1 While @i <= @MaxI Begin Select @UserID = UserID from @TableUsers Where MyRowCount = @i Exec prMyStoredProc @UserID Select @i = @i + 1, @UserID = null End 

这不能用用户定义的函数来完成,不pipe你的存储过程在做什么?

 SELECT udfMyFunction(user_id), someOtherField, etc FROM MyTable WHERE WhateverCondition 

其中udfMyFunction是你所做的一个函数,它使用用户ID,并做任何你需要做的事情。

请参阅http://www.sqlteam.com/article/user-defined-functions了解更多背景信息;

我同意游戏真的应该尽可能避免。 这通常是可能的!

(当然,我的答案是假设你只想从SP获得输出,而不是改变实际数据,我发现“以某种方式改变用户数据”与原来的问题有些模糊,所以我认为我会提供这个解决scheme,完全取决于你在做什么!)

你可以用dynamic查询来完成。

 declare @cadena varchar(max) = '' select @cadena = @cadena + 'exec spAPI ' + ltrim(id) + ';' from sysobjects; exec(@cadena); 

我喜欢Dave Rincon的dynamic查询方式,因为它不使用游标,而且又小又简单。 谢谢戴夫分享。

但是,对于我在Azure SQL上的需求和查询中的“独特”,我不得不像这样修改代码:

 Declare @SQL nvarchar(max); -- Set SQL Variable -- Prepare exec command for each distinctive tenantid found in Machines SELECT @SQL = (Select distinct 'exec dbo.sp_S2_Laser_to_cache ' + convert(varchar(8),tenantid) + ';' from Dim_Machine where iscurrent = 1 FOR XML PATH('')) --for debugging print the sql print @SQL; --execute the generated sql script exec sp_executesql @SQL; 

我希望这可以帮助别人