我有一個以某種方式改變用戶數據的存儲過程。我把它傳遞給user_id,它做的是事情。我想在一個表上運行一個查詢,然後爲每個user_id找到運行存儲過程一次user_id如何爲查詢返回的每一行執行一次存儲過程?
我該如何爲此編寫查詢?
我有一個以某種方式改變用戶數據的存儲過程。我把它傳遞給user_id,它做的是事情。我想在一個表上運行一個查詢,然後爲每個user_id找到運行存儲過程一次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循環;更多詳細信息in this SO question
附錄2:如果您要處理的不僅僅是幾條記錄,請先將它們拉入臨時表中,然後將光標移到臨時表上;這將防止SQL升級到表鎖並加速運行
附錄3:當然,如果您可以內聯任何存儲過程對每個用戶ID執行的操作並將整個事件作爲單個SQL更新語句,那將是最佳的
類似這樣的替換將需要您的表和字段名稱。
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
如果您需要循環嘗試更改您的方法!
在父存儲過程中,創建一個#temp表,其中包含您需要處理的數據。調用子存儲過程,#temp表將可見,並且可以對其進行處理,希望能夠處理整組數據,而不需要光標或循環。
這真的取決於這個子存儲過程在做什麼。如果你正在更新,你可以「更新」加入#temp表格,並在一個語句中完成所有工作而不需要循環。對於INSERT和DELETE也可以做同樣的事情。如果您需要使用IF執行多個更新,則可以使用#temp表將其轉換爲多個UPDATE FROM
,並使用CASE語句或WHERE條件。
在數據庫中工作時,嘗試失去循環的心態,這是一個真正的性能消耗,會導致鎖定/阻塞並放慢處理速度。如果你到處循環,你的系統不能很好地擴展,當用戶開始抱怨緩慢刷新時,加速很難。
發佈您想要循環調用的此過程的內容,並且我會下注9次,您可以將它寫入一組行中。
這不能用用戶定義的函數來完成複製存儲過程的任何操作嗎?
SELECT udfMyFunction(user_id), someOtherField, etc FROM MyTable WHERE WhateverCondition
其中udfMyFunction是你做一個函數具有在用戶ID和做任何你需要用它做。
多一點背景
見http://www.sqlteam.com/article/user-defined-functions我同意光標真的應該儘可能地避免。它通常是可能的! (當然,我的答案假定你只是想從SP獲得輸出,而你並沒有改變實際數據,我發現「以某種方式改變了用戶數據」,這有點含糊不清原來的問題,所以我認爲我會提供這個作爲一個可能的解決方案。完全取決於你在做什麼!)
你可以做一個動態查詢。
declare @cadena varchar(max) = ''
select @cadena = @cadena + 'exec spAPI ' + ltrim(id) + ';'
from sysobjects;
exec(@cadena);
我喜歡Dave Rincon的動態查詢方式,因爲它不使用遊標,而且小巧易用。謝謝戴夫分享。
但對於我在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;
我希望這可以幫助別人......
您需要指定什麼RDBMS - 對於SQL Server,Oracle,MySql等,答案會有所不同。 – 2009-05-20 05:33:45
很可能您根本不需要存儲過程。你能概述存儲過程的「什麼」嗎?也許整個過程可以表示爲單個更新語句。如果可能,通常應避免「爲每個記錄做一次」模式。 – Tomalak 2009-05-20 05:38:11
您正在使用哪個數據庫? – 2009-05-20 05:38:19