J'ai une très grande table, j'utilise donc les éléments suivants pour supprimer les entrées plus anciennes:
WHILE (@@ROWCOUNT > 0)
BEGIN
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
END
Je l'ai couru plusieurs fois en utilisant des dates différentes. Parfois, cela fonctionne bien (prend environ 20 minutes), mais parfois, la requête se termine immédiatement et rien n'a été supprimé. Lorsque cela se produit, je fais simplement une instruction SELECT simple à partir de cette table, puis réessaie l'instruction WHILE ci-dessus, puis tout fonctionne! Quelqu'un sait pourquoi c'est? J'ai besoin d'automatiser cette requête pour qu'elle s'exécute régulièrement afin de contrôler la taille de la table, mais je veux m'assurer qu'elle est correctement supprimée lors de son exécution. Je vous remercie.
Vraisemblablement, la raison est parce que @@ROWCOUNT
est initialisé à une valeur de 0.
Vous pouvez d'abord lancer cette requête pour la définir:
select count(*) from myTable where date < 20130103
Cela ajouterait un peu de temps à votre requête, mais vous verriez le nombre de lignes supprimées.
Vous pouvez aussi faire quelque chose comme:
select top 1 * from myTable
ce qui irait beaucoup plus vite.
Qu'est-ce que vous exécutez avant ce bloc de code? @@ROWCOUNT
sera défini sur l’instruction qui l’a précédé. Si vous exécutez une autre commande au préalable, il pourrait s'agir de 0
.
Au lieu de cela, vous pouvez forcer le nombre initial à être 1
:
DECLARE @Rows INT
SET @Rows = 1
WHILE (@Rows > 0)
BEGIN
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
SET @Rows = @@ROWCOUNT
END
C'est parce que parfois @@ROWCOUNT
est zéro pour commencer - ainsi la boucle while
ne s'exécute jamais, car elle vérifie la condition before chaque exécution, y compris la première.
Voici une boucle do-while
faite maison, car SQL Server n’en a pas.
loop:
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
if @@ROWCOUNT > 0 goto loop
Vous pouvez également écrire votre requête de cette façon:
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"
Dans les deux cas, vous devez formater correctement vos chaînes de date.
Assurez-vous simplement que vos critères de suppression et l’énoncé de votre clause exist sont identiques ou vous risquez de rencontrer une boucle infinie.
Lorsque je supprime en lot, j'ajoute un WAITFOR DELAY (au moins 1 ou 2 secondes). Aussi la première déclaration que j'ai créée en dehors de la boucle. Par ailleurs, évitez d'utiliser ROWCOUNT comme délimiteur ( https://docs.Microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017 ) . Il y a deux options:
DECLARE @BatchSize BIGINT = 50000
SET ROWCOUNT @BatchSize
DELETE
FROM myTable
WHERE
date < 20130103
WHILE (@@ROWCOUNT > 0)
BEGIN
WAITFOR DELAY '00:00:02'
DELETE
FROM myTable
WHERE
date < 20130103
END
Ou
DECLARE @BatchSize BIGINT = 50000
WHILE 1=1
BEGIN
WAITFOR DELAY '00:00:02'
DELETE TOP(@BatchSize )
FROM myTable
WHERE
date < 20130103
IF @@ROWCOUNT < @BatchSize
Break
END
Fondamentalement,
SELECT 0 -- rowcount is 1
WHILE (@@ROWCOUNT > 0)
BEGIN
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
END
Ou
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