23

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

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

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

4

6 回答 6

48

在这段代码之前你在运行什么? @@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
于 2013-03-21T21:09:52.003 回答
11

据推测,原因是因为@@ROWCOUNT被初始化为0的值。

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

select count(*) from myTable where date < 20130103

这会为您的查询增加一点时间,但您会看到被删除的行数。

您还可以执行以下操作:

select top 1     * from myTable 

这会快得多。

于 2013-03-21T21:08:06.407 回答
6

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

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

loop:
   DELETE TOP (5000) FROM myTable
   WHERE date < 20130103
if @@ROWCOUNT > 0 goto loop
于 2013-03-21T21:11:35.167 回答
5

当我批量删除时,我添加了一个等待延迟(至少 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

或者

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
于 2018-09-06T22:10:15.623 回答
2

基本上,

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
于 2017-08-23T11:14:41.543 回答
1

你也可以这样写你的查询:

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"

无论哪种方式,您都应该正确格式化您的日期字符串。

只要确保您的删除条件和您的存在子句中的语句相同,否则您可能会遇到无限循环。

于 2013-06-18T19:02:10.357 回答