我们试图在DELETE
循环内运行一个WHILE
语句(以避免大量行的大型事务日志),如下所示:
WHILE (@@ROWCOUNT > 0)
BEGIN
DELETE TOP (250000)
FROM
MYDATABASE.MYSCHEMA.MYTABLE
WHERE
MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301
END
在 development 环境中的新SQL Server Management Studio连接中执行此命令时,它会删除250K块中的行,这是预期的行为。
在我们的 test 服务器上以相同的方式执行此命令时,我们会收到消息
Command completed successfully
也就是说,在语句运行时没有输入WHILE
循环。
经过一些额外的调查后,我们发现行为也会因我们连接的数据库而异。因此,如果在SQL Server Management Studio连接到MYDATABASE
时运行代码(在我们的 test 环境中),则DELETE
语句不会运行。如果我们在连接到SOME_OTHER_DATABASE
时运行代码,则会执行。
我们部分怀疑@@ROWCOUNT
的值不可靠,并且对于不同的连接可能有所不同。但是当我们为每个数据库运行代码多次时服务器组合,我们看到100%一致的行为。所以@@ROWCOUNT
的随机初始值似乎不能解释事情。
有关可能发生的事情的任何建议吗?谢谢你的帮助!
编辑#1
对于那些询问@@ROWCOUNT
的初始值及其来源的人,我们不确定。但在某些情况下,@@ROWCOUNT
肯定被初始化为零以上的某个值,因为代码按原样处理新连接。
编辑#2
对于那些提出我们自己的变量声明的人,对于我们的特定应用程序,我们通过编程语言包装器执行SQL命令,它只允许一次执行一个语句(即一个分号)。
我们之前尝试通过在循环之前执行一个delete语句来建立@@ROWCOUNT
的值:
声明#1:
DELETE TOP (250000)
FROM
MYDATABASE.MYSCHEMA.MYTABLE
WHERE
MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301
声明#2(@@ROWCOUNT
现在可能是250,000):
WHILE (@@ROWCOUNT > 0)
BEGIN
DELETE TOP (250000)
FROM
MYDATABASE.MYSCHEMA.MYTABLE
WHERE
MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301
END
但是,导致@@ROWCOUNT
在启动时采用不同值的任何因素也会影响命令之间的值。所以在某些情况下,第二个语句永远不会执行。
答案 0 :(得分:2)
在设置其值之前,不应使用变量。系统变量同样如此。
你拥有的代码非常危险。有人可以在SELECT 'Here I am in the loop'
之后添加类似delete
的内容,它会中断。
更好的方法?使用您自己的变量:
DELCARE @RC int;
WHILE (@RC > 0 OR @RC IS NULL)
BEGIN
DELETE TOP (250000)
FROM MYDATABASE.MYSCHEMA.MYTABLE
WHERE MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301;
SET @RC = @@ROWCOUNT;
END;
答案 1 :(得分:0)
你从哪里获得最初的@@ROWCOUNT
?我的意思是,你永远不会进入那个区块,因为@@ROWCOUNT
预计会为零,所以你永远不会进入循环。此外,以250K批次删除不会改变事务日志的大小 - 如果您正在记录,将记录所有删除,因此这样做没有任何好处(和一些惩罚)在一个循环中。
答案 2 :(得分:0)
您是否跟踪过会话?由于@@ROWCOUNT
返回会话中先前语句影响的行数,我猜想最后一个查询SSMS作为建立会话的一部分执行会在两个环境中返回不同数量的行,或者你有一个或另一个环境中的登录触发器,其最后一个语句返回不同的行数。无论哪种方式,跟踪都应该告诉您行为不同的确切原因。
但是,从根本上说,在运行您感兴趣的语句之前引用@@ROWCOUNT
是没有意义的。使用变量
DECLARE cnt integer = -1;
WHILE (cnt != 0)
BEGIN
DELETE TOP (250000)
FROM MYDATABASE.MYSCHEMA.MYTABLE
WHERE MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301;
SET cnt = @@ROWCOUNT;
END