2010-04-05 69 views
1

不難找到開發商who think cursors are gauche但我想知道如何解決以下問題沒有一個得到的:運行存儲過程帶有參數的查詢

比方說,我有一個進程稱爲uspStudentDelete是作爲一個參數@學生卡。

uspStudentDelete應用於一堆級聯軟刪除邏輯,就像「類」,「等級」,表格標記的標誌等爲不活動的。 uspStudentDelete經過了充分的審查並已經工作了一段時間。

什麼是運行在一個查詢的結果uspStudentDelete的最佳方式(如選擇studentid從學生那裏......)TSQL

+3

光標是不笨拙,它們是性能殺手。只要數據集運行時間很大,就應該避免使用它們。它可能會花費數小時或數天或毫秒或分鐘的過程。 – HLGEM 2010-04-05 21:32:27

+0

這顯然取決於。對於大量文件,應該使刪除過程能夠處理多個學生,並以基於集合的方式(HLGEM的解決方案)執行所有依賴刪除。對於小批量,調用單一學生刪除將不會表現不佳,並且無需重新編寫SP(Andomar的解決方案)。 – 2010-04-06 04:59:44

+0

**可以循環無光標。**我不得不加快速度慢光標循環那裏是瘋了,如果邏輯並調用在循環中許多其他程序。在某些情況下,不可能刪除循環。但是我刪除了光標(離開了循環),並且仍然有顯着的性能改進。只是谷歌「SQL服務器遊標免費循環」 – 2010-04-06 12:12:58

回答

3

這正是光標打算什麼:

誰反對光標軌認爲你應該在合適的客戶做到這一點,像一個C#桌面應用程序
declare c cursor local for <your query here> 
declare @ID int 
open c 
fetch next from c into @id 
while @@fetch_status = 0 
    begin 
    exec uspStudentDelete @id 
    fetch next from c into @id 
    end 
close c 
deallocate c 

大多數人。

+2

這正是你不應該做的。這會殺死性能。 – HLGEM 2010-04-05 21:26:25

+1

@HLGem:該OP說,他目前的proc「以及審查」,所以我想重用以及審覈的代碼比性能更重要。並希望他不會每天刪除10,000名學生:) – Andomar 2010-04-05 21:35:16

+0

@HLGem:@Andomar在這兩方面都是正確的 - 首先,這個過程在我們的許多開發週期中已經存在,作爲該過程的關鍵部分,而且我們正在討論一些最多的記錄,遠不及50+的記錄。我所說的是,你所說的是在複製/粘貼現有​​的基於SET的邏輯,以在兩個地方存在,這會引入另一個問題:可維護性。 – t3rse 2010-04-05 21:47:33

3

最好的解決辦法是寫一個基於集合的PROC來處理刪除(嘗試通過遊標運行此刪除10000條記錄,你就會明白爲什麼),或在基於集合的代碼添加到當前PROC一個參數告訴你什麼時候運行proc的基於set或單個記錄部分(這至少將它保持在一起用於維護目的)。

在SQL Server 2008中您可以使用一個表變量作爲輸入變量。如果你重寫proc是基於set的,你可以擁有相同的邏輯並運行它,不管proc是發送一個記錄還是一萬個記錄。您可能需要在那裏進行批處理,以避免一次刪除數百萬條記錄,並將表格鎖定數小時。當然,如果你這樣做,你還需要調整currect sp的調用方式。

+1

+1阿門,兄弟!一些基於集合的重構可以幫助輕鬆避免這裏的遊標 – 2010-04-06 06:51:44