如何正确地检查记录是否存在

在阅读一些SQL调优相关文档时,我发现了这个:

SELECT COUNT(*):

  • 计算行数。
  • 通常不恰当地用于验证记录的存在。

SELECT COUNT(*)真的那么糟糕吗?

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

591622 次浏览

你可以使用:

SELECT COUNT(1) FROM MyTable WHERE ...

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

这将比SELECT *更有效,因为您只是为每行选择值1,而不是所有字段。

COUNT(*)和COUNT(列名)之间也有细微的区别:

  • COUNT(*)将计数所有行,包括空值
  • COUNT(column name)将只计算列名的非空事件

你可以使用:

SELECT 1 FROM MyTable WHERE <MyCondition>

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

我宁愿不使用Count函数:

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

例如,如果你想在将user插入数据库之前检查它是否存在,查询可以是这样的:

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

其他答案都很好,但添加LIMIT 1(或相当于)也很有用,以防止检查不必要的行。

最好使用以下任何一种:

-- Method 1.
SELECT 1
FROM table_name
WHERE unique_key = value;


-- Method 2.
SELECT COUNT(1)
FROM table_name
WHERE unique_key = value;

第一个选项应该没有结果或只有一个结果,第二个计数应该是0或1。

您使用的文档是什么时候的?虽然你已经读过很好的建议,但最近RDBMS中的大多数查询优化器都优化了SELECT COUNT(*),所以虽然在理论上(和旧的数据库)有区别,但在实践中你不应该注意到任何区别。

SELECT COUNT(1) FROM MyTable WHERE ...

将遍历所有记录。这就是它不适合用于记录存在的原因。

我会用

SELECT TOP 1 * FROM MyTable WHERE ...

在找到一条记录后,它将终止循环。

你可以使用:

SELECT 1 FROM MyTable WHERE... LIMIT 1

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

使用LIMIT 1来防止检查不必要的行。

我是这么说的:

IF (EXISTS (SELECT TOP 1 FROM Users WHERE FirstName = 'John'), 1, 0) AS DoesJohnExist

其他选项:

SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [MyTable] AS [MyRecord])
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END