2013-03-21 18 views
9
funktioniert

ich einen sehr großen Tisch, so dass ich bin mit dem folgend älteren Einträge löschen:SQL-Batch-Server löscht, während Schleife nicht

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

Ich betreiben habe dies ein paar Mal verschiedene Daten verwendet wird. Manchmal funktioniert es gut (dauert etwa 20 Minuten), aber zu anderen Zeiten wird die Abfrage sofort beendet und nichts wurde gelöscht. Wenn das passiert, mache ich einfach eine einfache SELECT-Anweisung aus dieser Tabelle und versuche dann die obige WHILE-Anweisung erneut, und dann funktioniert es! Wer weiß, warum das so ist? Ich muss diese Abfrage automatisieren, um regelmäßig die Tabellengröße zu steuern, aber ich möchte sicherstellen, dass es tatsächlich ordnungsgemäß löscht, wenn es ausgeführt wird. Vielen Dank.

+6

Sollte nicht das Datum geschrieben werden als ' '2013-01-03'' und nicht als Nummer? –

+0

Komisch, dass jede Antwort das komplett vermisst hat. –

+4

Beachten Sie auch, dass das Vorhandensein einer Schleife nicht unbedingt die Auswirkungen auf das Protokoll oder die Nebenläufigkeit reduziert, je nachdem, ob es sich um eine einzelne Transaktion handelt.Ich würde aufhören zu @@ ROWCOUNT für die Kontrolle, fügen Sie Transaktionen innerhalb der Schleife, und legen Sie eine Variable = @@ ROWCOUNT. Siehe http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes –

Antwort

8

Vermutlich ist der Grund, weil @@ROWCOUNT auf einen Wert von 0.

initialisiert

Sie diese Abfrage zuerst einzustellen laufen konnte:

select count(*) from myTable where date < 20130103 

ein wenig Zeit, um Ihr Dies würde hinzufügen Abfrage, aber Sie würden die Anzahl der Zeilen sehen, die gelöscht werden.

Man könnte auch so etwas wie tun:

select top 1  * from myTable 

die viel schneller gehen würde.

+8

Sie können auch vor der Schleife einfach 'SELECT 1;' wählen. –

27

Was läuft vor diesem Codeblock? @@ROWCOUNT wird auf welche Anweisung auch immer ausgeführt .. wenn Sie vorher einen anderen Befehl ausführen, könnte es 0 sein.

Stattdessen könnten Sie die anfängliche Anzahl zwingen 1 zu sein:

DECLARE @Rows INT 
SET @Rows = 1 

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

    SET @Rows = @@ROWCOUNT 
END 
4

Es ist manchmal, weil @@ROWCOUNT Null ist, mit zu beginnen - so die while Schleife niemals ausgeführt, weil sie die Bedingung vor prüft jede Ausführung einschließlich der ersten.

Hier ist eine hausgemachte do-while Schleife, da SQL Server nicht eine eingebaute hat

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

SQL Server hat kein ['WHILE'loop] (http://msdn.microsoft.com/en-us/library/ms178642 (v = sql.100) .aspx)? –

+5

@AaronBertrand spricht er von einer 'Do-While'-Schleife. Wie in: 'DO BEGIN END WHILE ' (führt immer die "" einmal vor der Überprüfung der Bedingung). Das ist in SQL Server nicht vorhanden. – EvilBob22

1

Sie können auch Ihre Abfrage auf diese Weise schreiben:.

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" 

So oder so, sollten Sie formatieren Ihre Datumszeichenfolgen richtig.

Stellen Sie sicher, dass Ihre Löschkriterien und die Anweisung in Ihrer exists-Klausel identisch sind oder dass eine Endlosschleife auftritt.

+3

Beachten Sie, dass nach SQL 2012: "SET ROWCOUNT wirkt sich nicht auf DELETE-, INSERT- und UPDATE-Anweisungen in einer zukünftigen Version von SQL Server. Vermeiden Sie SET ROWCOUNT mit DELETE, INSERT und UPDATE-Anweisungen in neue Entwicklungsarbeit und planen Ändern Sie Anwendungen, die es derzeit verwenden. Verwenden Sie für ein ähnliches Verhalten die TOP-Syntax. " –

0

Grundsätzlich

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

Oder

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