使用WHILE循环的SQL Server批量删除不起作用

JCB*_*JCB 16 sql sql-server rowcount

我有一个非常大的表,所以我使用以下内容删除旧条目:

WHILE (@@ROWCOUNT > 0)
BEGIN
    DELETE TOP (5000) FROM myTable
    WHERE date < 20130103
END
Run Code Online (Sandbox Code Playgroud)

我使用不同的日期运行了几次.有时它工作正常(大约需要20分钟),但有时候查询会立即完成,并且没有删除任何内容.当发生这种情况时,我只是从该表中执行一个简单的SELECT语句,然后再次尝试上面的WHILE语句,然后它就可以了!有谁知道这是为什么?我需要自动执行此查询以定期运行以控制表大小,但我想确保它在运行时实际上正确删除.谢谢.

Mic*_*son 33

在这段代码之前你在运行什么? @@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
Run Code Online (Sandbox Code Playgroud)


Gor*_*off 10

据推测,原因是因为@@ROWCOUNT初始化为0.

您可以先运行此查询来设置它:

select count(*) from myTable where date < 20130103
Run Code Online (Sandbox Code Playgroud)

这会为您的查询添加一点时间,但您会看到要删除的行数.

你也可以这样做:

select top 1     * from myTable 
Run Code Online (Sandbox Code Playgroud)

哪个会快得多.

  • 你也可以在循环之前选择`SELECT 1;`. (12认同)

Blo*_*ard 6

这是因为有时候@@ROWCOUNT开始时为零 - 所以while循环永远不会执行,因为它会每次执行之前检查条件,包括第一个.

这是一个自制的do-while循环,因为SQL Server没有内置的循环.

loop:
   DELETE TOP (5000) FROM myTable
   WHERE date < 20130103
if @@ROWCOUNT > 0 goto loop
Run Code Online (Sandbox Code Playgroud)

  • @AaronBertrand他在谈论一个`do-while`循环.如:`DO BEGIN <something> END WHILE <condition>`(在检查条件之前总是运行"<something>"一次).这在SQL Server中不存在. (6认同)

Edu*_*vis 5

当我批量删除时,我添加了 WAITFOR DELAY(至少 1 或 2 秒)。也是我在循环外创建的第一条语句。顺便说一句,避免使用 ROWCOUNT 作为分隔符(https://docs.microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017)。有两个选项:

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
Run Code Online (Sandbox Code Playgroud)

或者

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
Run Code Online (Sandbox Code Playgroud)