2010-11-23 73 views
133

阅读一些SQL调优文档,我发现这一点:SQL:如何正确检查是否存在记录

Select count(*)
- 计数行
的数量 - 往往是使用不当,以验证是否存在创纪录

Select count(*)真的那么糟糕?

什么是验证记录存在的正确方法?

回答

163

这是更好地使用

select 1 
from table 
where key = value; 

select count(1) 
from table 
where key = value; 

第一个选择应该给你任何结果或一个结果,第二计数应为0或1。

您使用的文档的年龄?虽然你已经阅读了很好的建议,但是最近RDBMS中的大多数查询优化器无论如何都优化了select count(*),所以尽管理论(和较老的数据库)有所不同,但在实践中你不应该注意到任何差异。

6

您可以使用:

SELECT COUNT(1) FROM MyTable WHERE ... 

WHERE [NOT] EXISTS 
(SELECT 1 FROM MyTable WHERE ...) 

这将是比SELECT *更有效,因为你只是选择值为1的每一行,而不是所有的领域。

还有COUNT(*)和COUNT(列名)之间的微妙区别:

  • COUNT(*)将计算所有的行,包括空
  • 只会算非空列名的出现
+1

您错误地认为DBMS会以某种方式检查所有这些列。 `count(1)`和`count(*)`之间的性能差异只有在大脑死亡的DBMS中才会有所不同。 – paxdiablo 2010-11-23 08:20:58

+0

** @ paxdiablo **你是否建议依靠实现细节是一个好主意? – 2010-11-23 08:24:05

+2

不,我说你实际上依赖于实现细节,当你声明它会更有效率。如果你真的想确保你获得最佳性能,你应该使用具有代表性的数据来​​描述它的具体实现,或者完全忘记它。其他任何东西都可能会引起误解,并且在从DB2移动到MySQL时可能会发生巨大变化。 – paxdiablo 2010-11-23 08:30:29

12

您可以使用:

SELECT 1 FROM MyTable WHERE <MyCondition> 

如果没有匹配条件的记录,则结果记录集为空。

126

我宁愿不要使用计数功能在所有:

IF [NOT] EXISTS (SELECT 1 FROM MyTable WHERE ...) 
    <do smth> 

例如,如果你想检查用户是否将其插入到数据库中的查询之前存在可以是这样的:

IF NOT EXISTS (SELECT 1 FROM Users WHERE FirstName = 'John' AND LastName = 'Smith') 
BEGIN 
    INSERT INTO Users (FirstName, LastName) VALUES ('John', 'Smith') 
END 
12

其他答案相当不错,但也可以加LIMIT 1(或the equivalent,防止检查不必要的行。

6
SELECT COUNT(1) FROM MyTable WHERE ... 

将循环所有记录。这就是使用记录存在不好的原因。

我会用

SELECT TOP 1 * FROM MyTable WHERE ... 

发现1次记录后,将终止循环。

5

您可以使用:

SELECT 1 FROM MyTable WHERE... LIMIT 1 

使用select 1,以防止不必要的字段的检查。使用LIMIT 1来防止检查不必要的行。