为什么@@ ROWCOUNT使用sp_executesql为NULL语句返回1?

时间:2019-07-01 15:34:44

标签: sql sql-server tsql null

如果我运行此命令:

DECLARE @sql NVARCHAR(10) = NULL;
EXEC sp_executesql @sql;
SELECT @@ROWCOUNT;

我希望得到0,甚至NULL也可以。但是我什么也没有,我得到1。为什么执行NULL查询会影响1行?如果我传递“适当的”(non_NULL)查询,那么它将正常工作。


背景(适用于那些关心的人):这来自一个应该生成一些动态SQL来更新一行而仅更新一行的过程。我需要检查1行是否受到影响,而不是0或2或多于2。它工作正常,直到设法生成NULL SQL语句,并且这被视为成功-糟糕!

实际的解决方法是在运行SQL之前检查SQL是否为非NULL,并以与1以外的结果相同的方式对待NULL语句。但是我仍然很好奇为什么它会以这种方式运行。

2 个答案:

答案 0 :(得分:4)

这是因为您要将NULL设置为变量。进行简单分配的语句始终将@@ ROWCOUNT的值设置为1。

请参见下面的示例。由于Management Studio可以在连接上运行自己的查询并与@@ROWCOUNT值混淆,因此它开始选择一个空结果集以确保初始@@ROWCOUNT值为零。

没有分配时,SELECT @@ROWCOUNT返回0(初始值尚未修改)。否则返回1

/*Ensure @@ROWCOUNT starts off at 0*/
SELECT 1 WHERE 1 = 0;

DECLARE @sql NVARCHAR(10);
EXEC sp_executesql @sql;
SELECT @@ROWCOUNT;

GO

/*Ensure @@ROWCOUNT starts off at 0*/
SELECT 1 WHERE 1 = 0;

DECLARE @sql NVARCHAR(10) = NULL;
EXEC sp_executesql @sql;
SELECT @@ROWCOUNT;

您也可以尝试将初始值设为非零

/*Ensure @@ROWCOUNT starts off at 3*/
SELECT 1 UNION SELECT 2 UNION SELECT 3

DECLARE @sql NVARCHAR(10);
EXEC sp_executesql @sql;
SELECT @@ROWCOUNT; --Returns 3

GO

/*Ensure @@ROWCOUNT starts off at 3*/
SELECT 1 UNION SELECT 2 UNION SELECT 3

DECLARE @sql NVARCHAR(10) = NULL;
EXEC sp_executesql @sql;
SELECT @@ROWCOUNT; --Returns 1

答案 1 :(得分:1)

请注意,我的回答纯粹是根据我对SQL Server Management Studio的经验编写的,并不能准确地解释这种行为。 Martin Smith在下面的comment中解释了为什么这不是真的。

看起来sp_executesql根本不使用null参数运行,也许作为故障保护。

尝试分批单独运行“ SELECT @@ ROWCOUNT”,无论当前没有行数,它都会返回1。默认返回值似乎是1,这就是为什么看到此值的原因。