2013-03-21 114 views
9

我有一個非常大的表,所以我用以下命令來刪除舊條目:SQL Server的批量刪除使用while循環沒有工作

WHILE (@@ROWCOUNT > 0) 
BEGIN 
    DELETE TOP (5000) FROM myTable 
    WHERE date < 20130103 
END 

我曾嘗試使用不同的日期該跑幾次。有時它可以正常工作(大約需要20分鐘),但其他時間查詢立即結束,沒有任何內容被刪除。當發生這種情況時,我只需從該表中做一個簡單的SELECT語句,然後再次嘗試上面的WHILE語句,然後它就可以工作!任何人都知道這是爲什麼?我需要自動執行此查詢以定期運行以控制表的大小,但是我想確保它在運行時實際刪除正確。謝謝。

+6

不宜日期寫爲''2013-01-03'',而不是爲一個數字? – 2013-03-21 21:10:31

+0

有趣的是,每一個答案完全錯過了。 – 2013-03-21 21:29:48

+4

另請注意,只是進行循環並不一定會降低對日誌或併發的影響,具體取決於它是否是單個事務。我將停止使用@@ ROWCOUNT進行控制,在循環內添加事務,並設置一個變量= @@ ROWCOUNT。請參閱http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes – 2013-03-21 21:37:27

回答

8

據推測,其原因是因爲@@ROWCOUNT被初始化爲0

值你可以運行此查詢先設置:

select count(*) from myTable where date < 20130103 

這時間一點點添加到您的查詢,但你會看到被刪除的行數。

你也可以這樣做:

select top 1  * from myTable 

它會去得更快。

+8

你也可以在循環之前選擇1;''。 – 2013-03-21 21:33:14

27

你在這段代碼之前運行什麼? @@ROWCOUNT將設置爲任何語句繼續它..如果您事先運行一些其他命令,它可能是0

相反,你可能會迫使初始計數爲1

DECLARE @Rows INT 
SET @Rows = 1 

WHILE (@Rows > 0) 
BEGIN 
    DELETE TOP (5000) FROM myTable 
    WHERE date < 20130103 

    SET @Rows = @@ROWCOUNT 
END 
4

這是因爲有時@@ROWCOUNT爲零下手 - 這樣的while循環永遠不會執行,因爲它每次執行之前檢查的條件,包括第一個。

這裏有一個自制的do-while循環,因爲SQL Server不具有內置的一個

loop: 
    DELETE TOP (5000) FROM myTable 
    WHERE date < 20130103 
if @@ROWCOUNT > 0 goto loop 
+1

SQL Server沒有['WHILE'loop](http://msdn.microsoft.com/zh-cn/library/ms178642(v = sql.100).aspx)? – 2013-03-21 21:34:25

+5

@AaronBertrand他正在談論一個'do-while'循環。如:「DO BEGIN END '(在檢查條件之前總是運行一次」「)。這在SQL Server中不存在。 – EvilBob22 2013-03-21 22:06:34

1

你也可以寫你的查詢是這樣的:。

SET ROWCOUNT 5000; -- set batch size 
WHILE EXISTS (SELECT 1 FROM myTable WHERE date < '2013-01-03') 
BEGIN 
    DELETE FROM myTable 
    WHERE date < '2013-01-03' 
END; 
SET ROWCOUNT 0; -- set batch size back to "no limit" 

無論哪種方式,你應該格式化你的日期字符串正確。

只要確定您的刪除條件和存在子句中的語句是相同的,或者您可能會遇到無限循環。

+3

請注意,在SQL 2012之後:「使用SET ROWCOUNT不會影響SQL Server未來版本中的DELETE,INSERT和UPDATE語句。避免在新開發工作中使用帶有DELETE,INSERT和UPDATE語句的SET ROWCOUNT,並計劃修改當前使用它的應用程序,對於類似的行爲,使用TOP語法。「 – 2016-12-29 14:24:00

0

基本上,

SELECT 0 -- rowcount is 1 
WHILE (@@ROWCOUNT > 0) 
BEGIN 
    DELETE TOP (5000) FROM myTable 
    WHERE date < 20130103 
END 

或者

SET ROWCOUNT 5000 -- set row count to 5000 
SELECT 0 -- rowcount is 1 
WHILE (@@ROWCOUNT > 0) 
BEGIN 
    DELETE FROM myTable 
    WHERE date < 20130103 
END 
SET ROWCOUNT 0 -- set rowcount to unlimited