是“从...中选择计数(*)”比@@ ROWCOUNT更可靠吗?

时间:2011-06-08 17:53:44

标签: sql sql-server

我有一个将记录插入临时表的proc。在伪代码中它看起来像这样:

Create temp table 
a. Insert rows into temp table based on stringent criteria
b. if no rows were inserted, insert based on less stringent criteria 
c. if there are still no rows, try again with even less stringent criteria
select from temp table

代码中有很多IF @@rowcount = 0个检查,以查看表中是否有任何行。问题是proc并没有真正做它看起来应该做的事情而且它正在插入相同的行两次(步骤a和c正在执行)。但是,如果我更改它以检查这种方式IF ( (select count(*) from @temp) = 0),则proc完全按预期工作。

这让我觉得@@rowcount不是解决这个问题的最佳方法。但我正通过SELECT COUNT(*)添加额外的工作。哪个更好的解决方案?

3 个答案:

答案 0 :(得分:4)

@@ rowcount是更好的解决方案。这项工作已经完成。选择count(*)会使数据库做更多的工作。

在检查@@ rowcount的值之前,您需要确保没有做一些会影响@@ rowcount值的事情。通常最好在执行insert语句后立即检查@@ rowcount。如果需要,可以将值赋给变量,以便稍后检查:

DECLARE @rows int 
...
[insert or update a table]
SET @rows = @@rowcount

在任何更改行计数的操作之后立即存储行计数将允许您多次使用该值。

答案 1 :(得分:2)

@@ ROWCOUNT将只检查上一个查询中的“受影响的行”。这可能有点深远,因为许多东西可以创建行或“影响”行,而某些选项不会向客户端返回值。

微软说:

在查询中进行赋值或在查询中使用RETURN的语句将@@ ROWCOUNT值设置为查询影响或读取的行数,例如:SELECT @local_variable = c1 FROM t1。

数据操作语言(DML)语句将@@ ROWCOUNT值设置为受查询影响的行数,并将该值返回给客户端。 DML语句可能不会向客户端发送任何行。

DECLARE CURSOR和FETCH将@@ ROWCOUNT值设置为1。

EXECUTE语句保留以前的@@ ROWCOUNT。

诸如USE,SET,DEALLOCATE CURSOR,CLOSE CURSOR,BEGIN TRANSACTION或COMMIT TRANSACTION之类的语句将ROWCOUNT值重置为0.


如果你没有得到你期望的@@ ROWCOUNT(这可能意味着你的查询比你的例子更复杂)我肯定会看到使用SELECT COUNT(*)选项,或者,如果你担心关于性能打击做这样的事情:

INSERT INTO temptable
(cols...)
SELECT
 COL = @VAL
FROM
 sourcetableorquery
 LEFT JOIN temptable on [check for existing row]
WHERE
 temptable.id is null

如果循环遍历大记录集,这将比count选项更快。

答案 2 :(得分:1)