Sha*_*eis 2 sql-server sql-server-2012
在最后一天更新表中的列时,我们的高级 DBA 向我展示了一种减少读取和争用的新技术。
伪代码是
WHILE
[always true condition]
BEGIN
UPDATE [...]
IF @@ROWCOUNT = 0 BREAK;
END
Run Code Online (Sandbox Code Playgroud)
但是,在运行此程序时,我不小心将“包含实际执行计划”留在了“消息”选项卡中,因此我看到重复出现此情况:
(1000 row(s) affected)
(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)
但是代码有效并且 WHILE 循环有效!
我的问题是,如果包括实际执行计划返回 1 行受影响,这不应该创建一个无限循环吗?
为什么没有被计算在内?
示例表如下:
USE [tempdb];
GO
CREATE TABLE [dbo].[UpdateMePlease]
([ID] INT IDENTITY(1, 1), [UselessNote] VARCHAR(10) DEFAULT 'Delete me!', [UpdateValue] VARCHAR(10) NULL)
GO
INSERT INTO [dbo].[UpdateMePlease] ([UselessNote]) DEFAULT VALUES;
GO 10000
SELECT * FROM [dbo].[UpdateMePlease];
/* turn Actual Execution Plan on here */
WHILE 1 = 1 BEGIN
UPDATE TOP (1000) [dbo].[UpdateMePlease]
SET [UpdateValue] = [UselessNote]
WHERE [UpdateValue] IS NULL;
IF @@ROWCOUNT = 0 BREAK
END
-- Clean up
DROP TABLE [dbo].[UpdateMePlease];
Run Code Online (Sandbox Code Playgroud)
这DONE_IN_PROC从执行计划的消息是完全独立的的WHILE循环,是不是在你的条件被检查BREAK。马丁删除了他的答案,但这在很大程度上是有意为之。根据您的客户端工具是否正在检索执行计划,您的查询不应有不同的行为 - 这会很糟糕。执行计划用于监控和审查,而不是用于影响实际行为。
请注意,逆也不一定是给定的 - 并非所有将填充的东西@@ROWCOUNT都会导致DONE_IN_PROC消息,例如
DECLARE @foo int, @x varchar(32) = 'hello';
SET @foo = @@ROWCOUNT;
PRINT @foo;
Run Code Online (Sandbox Code Playgroud)
这将1在消息窗格中产生,但您不会看到1 row(s) affected.
现在,我一直非常喜欢使用SET NOCOUNT ON;,这使这个问题变得毫无意义。但似乎DONE_IN_PROC在现代版本中的影响不像我形成这个观点时那样:
| 归档时间: |
|
| 查看次数: |
175 次 |
| 最近记录: |