私は非常に大きなテーブルを持っているので、古いエントリを削除するために以下を使用しています:
WHILE (@@ROWCOUNT > 0)
BEGIN
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
END
異なる日付を使用してこれを数回実行しました。正常に動作することもありますが(約20分かかります)、クエリがすぐに終了して何も削除されない場合もあります。その場合は、そのテーブルから単純なSELECTステートメントを実行してから、上記のWHILEステートメントを再試行すると機能します。これがなぜか誰でも知っていますか?このクエリを自動化して定期的に実行し、テーブルサイズを制御する必要がありますが、実行時に実際に正しく削除されることを確認したいと思います。ありがとうございました。
おそらく、その理由は@@ROWCOUNT
は値0に初期化されます。
最初にこのクエリを実行して設定できます。
select count(*) from myTable where date < 20130103
これにより、クエリに少し時間が追加されますが、削除される行の数が表示されます。
次のようなこともできます:
select top 1 * from myTable
はるかに速くなります。
このコードブロックの前に何を実行していますか? @@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
それは時々@@ROWCOUNT
は最初はゼロです-したがって、while
ループは、条件beforeをチェックするため、最初の実行を含むすべての実行を実行するため、実行されません。
これが自家製do-while
ループ。SQLServerにはビルトインされていないため。
loop:
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
if @@ROWCOUNT > 0 goto loop
バッチで削除する場合、WAITFOR DELAY(少なくとも1秒または2秒)を追加します。また、ループの外側で作成した最初のステートメント。ところで、区切り文字としてROWCOUNTを使用しないでください( https://docs.Microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017 )。 2つのオプションがあります。
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
または
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
基本的に、
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
次のようにクエリを記述することもできます。
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"
どちらの方法でも、日付文字列を適切にフォーマットする必要があります。
削除条件とexists句のステートメントが同じであることを確認してください。そうしないと、無限ループが発生する可能性があります。