在一个SQL Server存储过程中计算删除行的数量

57
在SQL Server 2005中,是否有一种删除行并告知实际删除行数的方法?可以使用相同条件的select count(*)语句,但我需要它是完全可信的。我的第一个想法是使用@@ROWCOUNT变量,但它没有设置,例如:
delete 
from mytable 
where datefield = '5-Oct-2008' 

select @@ROWCOUNT 

总是返回0。

MSDN建议使用OUTPUT语法结构,例如:

delete from mytable 
where datefield = '5-Oct-2008' 
output datefield into #doomed

select count(*) 
from #doomed

这实际上会因为语法错误而失败。

有任何想法吗?

7个回答

59

你试过使用 SET NOCOUNT OFF 吗?


我曾经以为我已经尝试过这个了 - 但显然没有,因为它像魔法一样奏效了 - 谢谢。 - Unsliced
1
MSDN似乎说SET NOCOUNT会影响打印输出。为什么这会影响@@ROWCOUNT?它不应该始终返回已删除的行数(在OP中)吗? - noelicus
这只是猜测。我认为设置 NOCOUNT 会告诉系统不必跟踪计数以使事情更有效率。 - wcm

11
我在SQL2000中使用@@ROWCOUNT来达到这个目的,没有遇到任何问题。但是请确保在检查计数之前不要无意间重置此计数(BOL:“该变量由不返回行的任何语句设置为0,例如IF语句”)。

8

只需要这样做:

SET NOCOUNT off ;
SELECT @p1 = @@ROWCOUNT

其中p1是你在存储过程中设置的输出参数。 希望这有所帮助。


6
在你的例子中,@@ROWCOUNT 应该可以工作 - 这是一种找出删除行数的正确方法。如果你正在尝试从你的应用程序中删除某些内容,那么你需要使用 SET NOCOUNT ON。
根据 MSDN 的 链接1,即使 SET NOCOUNT 为 ON,@@ROWCOUNT 函数也会更新,因为 SET NOCOUNT 只影响执行后得到的消息。
因此,如果你想从 ADO.NET 等工具中使用 @@ROWCOUNT 的结果,则 SET NOCOUNT ON 绝对会有所帮助。

这与被接受的答案完全相反。 - Doug S

1
我发现在某些情况下无法使用@@rowcount,例如当你想知道删除的唯一值计数而不是总计数时。在这种情况下,你需要执行以下操作:
delete from mytable 
where datefield = '5-Oct-2008' 
output deleted.datefield into #doomed

select count(distinct datefield)
from #doomed

这个问题的语法错误是因为outputdatefield字段名之前没有包含deleted


0

出于好奇,你是如何调用这个过程的?(我假设它是一个存储过程?)我问这个问题是因为存储过程的返回值(在这种情况下应该是0)和行集结果之间有区别——在这种情况下,行集结果将是单行单列。在ADO.Net中,前者可以通过参数访问,后者可以通过SqlDataReader访问。也许你把过程的返回值误认为是行数了吗?


这段代码都在一个地方(但是是在存储过程中) - 我正在删除一些数据,然后将该事实写入状态表,所以这并不是因为返回值而感到困惑的情况。 - Unsliced

-1

创建一个只有一列id的临时表。

将要删除的id插入到临时表中。这样可以得到计数。

从你的表中删除id在(从临时表中选择的id)中的记录。


1
虽然这样做是可行的,但这样做的开销是浪费的。 - Mitchel Sellers
这样做的性能确实很差,查询至少需要多花费2倍的时间,如果你正在处理大量记录,则可能需要相当长的时间。不过,这是一种有创意的思维方式! - Karel-Jan Misseghers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接