2013-03-21 18 views
9

Mam bardzo duży stół, więc używam następujących usunąć starsze wpisy:SQL Server partia usuwać za pomocą pętli while nie działa

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

mam uruchomić ten kilka razy stosując różne daty. Czasem działa dobrze (trwa około 20 minut), ale w innych przypadkach zapytanie kończy się natychmiast i nic nie zostało usunięte. Kiedy tak się dzieje, po prostu wykonuję prostą instrukcję SELECT z tej tabeli, a następnie wypróbuję powyższą instrukcję WHILE ponownie, a następnie działa! Ktoś wie, dlaczego tak jest? Muszę zautomatyzować tę kwerendę, aby działała regularnie, aby kontrolować rozmiar tabeli, ale chcę się upewnić, że faktycznie usuwa się poprawnie po uruchomieniu. Dziękuję Ci.

+6

Jeżeli data nie być zapisany jako ' '2013-01-03'' raczej niż jako liczby? –

+0

Zabawne, że każda odpowiedź całkowicie to pominęła. –

+4

Należy również pamiętać, że samo posiadanie pętli niekoniecznie zmniejsza wpływ na dziennik lub współbieżność w zależności od tego, czy jest to pojedyncza transakcja.Przestanę używać @@ ROWCOUNT do kontroli, dodawania transakcji w pętli i ustawiania zmiennej = @@ ROWCOUNT. Zobacz http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes –

Odpowiedz

8

Można przypuszczać, że powodem jest to @@ROWCOUNT jest inicjowany do wartości 0.

Można uruchomić tę kwerendę najpierw ustawić go:

select count(*) from myTable where date < 20130103 

byłoby to dodać trochę czasu swoim zapytanie, ale zobaczysz liczbę usuniętych wierszy.

Można też zrobić coś takiego:

select top 1  * from myTable 

który pójdzie znacznie szybciej.

+8

Możesz także po prostu "WYBIERZ 1" przed pętlą. –

27

Co słychać przed tym blokiem kodu? @@ROWCOUNT zostanie ustawione na dowolną instrukcję, która kontynuowała. Jeśli wcześniej wykonasz inne polecenie, może to być 0.

Zamiast tego, można wymusić początkową liczbę być 1:

DECLARE @Rows INT 
SET @Rows = 1 

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

    SET @Rows = @@ROWCOUNT 
END 
4

To dlatego czasami @@ROWCOUNT wynosi zero zacząć - tak pętla while nie wykonuje, ponieważ sprawdza stan przed każdym wykonaniu , w tym pierwszy.

Oto domowe do-while pętla, ponieważ SQL Server nie posiada jeden wbudowany w

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

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

+5

@AaronBertrand on mówi o pętli 'do-while'. Tak jak w: 'DO BEGIN END PODCZAS ' (zawsze uruchamia "" raz przed sprawdzeniem warunku). TO nie istnieje w SQL Server. – EvilBob22

1

Można również napisać zapytanie w ten sposób:.

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" 

Tak czy inaczej, należy sformatować Twoje ciągi daty są poprawne.

Po prostu upewnij się, że twoje kryteria usuwania i instrukcja w Twojej klauzuli exist są identyczne lub możesz napotkać nieskończoną pętlę.

+3

Należy pamiętać, że po SQL 2012: "Korzystanie z SET ROWCOUNT nie wpłynie na polecenia DELETE, INSERT i UPDATE w przyszłej wersji SQL Server.Unikać używania SET ROWCOUNT z instrukcjami DELETE, INSERT i UPDATE w nowych pracach rozwojowych i planować zmodyfikuj aplikacje, które obecnie go używają. Aby uzyskać podobne zachowanie, użyj składni TOP. " –

0

Zasadniczo

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

Albo

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 
Powiązane problemy