我有一个非常大的表,所以我使用以下内容删除旧条目:
WHILE (@@ROWCOUNT > 0)
BEGIN
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
END
我使用不同的日期运行了几次。有时它工作正常(大约需要20分钟),但有时候查询会立即完成,并且没有删除任何内容。当发生这种情况时,我只是从该表中执行一个简单的SELECT语句,然后再次尝试上面的WHILE语句,然后它就可以了!有谁知道这是为什么?我需要自动执行此查询以定期运行以控制表大小,但我想确保它在运行时实际上正确删除。谢谢。
答案 0 :(得分:31)
在这段代码之前你在运行什么? @@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
答案 1 :(得分:10)
据推测,原因是因为@@ROWCOUNT
被初始化为值0。
您可以先运行此查询来设置它:
select count(*) from myTable where date < 20130103
这会为您的查询添加一点时间,但您会看到要删除的行数。
您还可以执行以下操作:
select top 1 * from myTable
会更快。
答案 2 :(得分:5)
这是因为有时 这是一个自制的@@ROWCOUNT
从零开始 - 所以while
循环永远不会执行,因为它会在每次执行之前检查条件,包括第一个。< / p>
do-while
循环,因为SQL Server没有内置的。loop:
DELETE TOP (5000) FROM myTable
WHERE date < 20130103
if @@ROWCOUNT > 0 goto loop
答案 3 :(得分: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"
无论哪种方式,您都应该正确格式化日期字符串。
请确保您的删除条件和您的exists子句中的语句相同,否则您可能会遇到无限循环。
答案 4 :(得分:1)
基本上,
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
或者
shuffle_batch
答案 5 :(得分:0)
当我批量删除时,我添加一个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
或
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