2009-01-25 16 views

回答

0

9的10倍,你可以做你想要的,沒有光標或一個while循環。但是,如果你必須使用一個,我發現雖然循環往往更快。

此外,如果你不想刪除或更新表,你可以使用這樣的事情:

DECLARE @id [type] 
SELECT @id = MIN([id]) FROM [table] 
WHILE @id IS NOT NULL 
BEGIN 
    EXEC [sproc] @id 
    SELECT @id = MIN([id]) FROM [table] WHERE [id] > @id 
END 
+1

這完全正確嗎?你可以通過id命令而不指定group by子句嗎? – 2010-06-25 16:12:43

+0

它不適用。閱讀最大ID後它不會停止。 – 2011-03-31 22:42:10

+1

-1不起作用。正如理查德科萊特所說,選擇語法被破壞。如果你修正了這個語法,那麼就像Tony_Henrich指出的那樣,它陷入了一個無限循環中)。我添加了一個有工作循環的答案,但是我的經驗很慢。 – 2012-04-17 17:31:43

17

是的。如果你有一列可以在表中使用,以紀念那些處理後,您可以使用,而存在:

DECLARE @Id int 
WHILE EXISTS(SELECT * FROM Table1 WHERE Processed='N') 
BEGIN 
SELECT Top 1 @Id = id from Table1 WHERE Procesed='N' 
EXEC dbo.Sproc @Id 
UPDATE Table1 SET Processed = 'Y' WHERE Id = @Id 
END 

或者,傾倒的ID到一個臨時表或表變量並刪除完成後:

DECLARE @HoldTable table (Id int PRIMARY KEY) 
DECLARE @Id int 
INSERT INTO @HoldTable SELECT Id FROM Table1 
WHILE EXISTS(SELECT * FROM @HoldTable) 
BEGIN 
SELECT @Id = id from @HoldTable 
EXEC dbo.Sproc @Id 
DELETE FROM @HoldTable where Id = @Id 
END 
+1

編輯你的第二個答案。您選擇的是@Id而不是@HoldTable,並且您有where子句,其中'processed ='N'`但是@HoldTable沒有這樣的列。第二個選項現在應該可以工作。我希望我能正確理解你的意圖。 – kralco626 2015-02-24 19:51:49

3

坦率地說,如果我需要執行一個存儲過程的一組數據,而不是當一個記錄它是寫的,我會寫基於集合的代碼,而不是使用存儲的過程。如果要針對大型數據集運行,這是執行此操作的唯一有效方法。您可以從幾個小時開始執行存儲過程所執行的插入,即秒或甚至毫秒。當您需要處理一組數據時,尤其不要使用基於記錄的處理,尤其是不要重複使用代碼等愚蠢的原因。性能勝過代碼的重用。

1

如果可能,我會寫一個從臨時表中讀取的存儲過程的第二個版本。

如果這不可能比你可能運氣不好。

12

如果您只使用SQL Server 2005或更新版本,不關心向後兼容性,並且可以將您的代碼轉換爲用戶定義函數(而不是存儲過程),那麼您可以使用新的「 CROSS APPLY「運算符,它使用的語法非常類似於你想要的。我發現here短的介紹(當然,你也可以閱讀波士和MSDN)

假設你的SP返回名爲out_int一個值,你的例子可以寫成:

SELECT T.id, UDF.out_int 
FROM 
    Table1 T 
CROSS APPLY 
    dbo.fn_My_UDF(T.id) AS UDF 

這將從Table1中檢索每個「id」並使用它來調用fn_My_UDF,其結果將顯示在除原始參數之外的最終結果集中。

「CROSS APPLY」的變體是「OUTER APPLY」。它們是「INNER JOIN」和「LEFT JOIN」的等價物,但是加入表和UDF(並同時調用第二個)。

如果你必須(按照尖頭髮老闆的明確命令)使用SP insead,好運氣!你必須保留光標,或嘗試作弊:將代碼改爲UDF,並創建包裝SP:D。

0

這個循環有效,但對我的SP來說很慢。我認爲HLGEM的正確答案是,您最好的辦法是編寫一個更好的批量查詢。

DECLARE @id INT 
SET @id = 0 

DECLARE @max INT 
SELECT TOP 1 @max = TableID 
FROM dbo.Table 
ORDER BY TableID desc 

-- loop until BREAK 
-- this is how you can perform a DO-WHILE loop in TSQL 
WHILE (1 = 1) 
BEGIN 
    SELECT  
     TOP 1 @id = TableID 
     FROM dbo.Table 
     WHERE TableID > @id 

    IF @id IS NOT NULL 
    BEGIN   
     -- call you SP here 
     PRINT @id   
    END 

    -- break out of the loop once the max id has been reached 
    IF @id = @max BREAK 
END 
相關問題