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

sys*_*out 186 sql optimization query-optimization

阅读一些SQL Tuning文档我发现了这个:

Select count(*):
- 计算行数
- 通常不正确地用于验证记录的存在

是否Select count(*)真的如此糟糕?

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

Mar*_*onk 226

最好使用以下任一方法:

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

-- Method 2.
SELECT COUNT(1)
FROM table_name
WHERE unique_key = value;
Run Code Online (Sandbox Code Playgroud)

第一个替代方案应该没有结果或一个结果,第二个计数应该是零或一个.

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


Pav*_*yuk 179

我宁愿不使用Count函数:

IF [NOT] EXISTS ( SELECT 1 FROM MyTable WHERE ... )
     <do smth>
Run Code Online (Sandbox Code Playgroud)

例如,如果要在将用户插入数据库之前检查用户是否存在,则查询可能如下所示:

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


Căt*_*tiș 18

您可以使用:

SELECT 1 FROM MyTable WHERE <MyCondition>
Run Code Online (Sandbox Code Playgroud)

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

  • 不,我的意思是"1" (6认同)
  • 为了使查询优化器知道您不会读取/不需要剩余的数据集,您应该声明 SELECT TOP 1 1 FROM... WHERE... (或为您的 RDBS 使用适当的查询提示) (3认同)
  • Exists操作符本身尝试仅检索绝对最小的信息,因此TOP 1的添加除了向查询大小添加5个字符外什么也不做. - http://www.sqlservercentral.com/blogs/sqlinthewild/2011/04/05/to-top-or-not-to-top-an-exists/ (2认同)

Jes*_*seW 12

其他答案非常好,但添加LIMIT 1(或等效,以防止检查不必要的行)也很有用.

  • 我正在考虑他们可以合法地成为多行的情况 - 问题是:"是否有(一个或多个)行满足这个条件?" 在这种情况下,您不希望看到所有这些,只有一个. (7认同)
  • 如果任何"检查存在"查询返回多行,我认为重复检查WHERE子句而不是限制结果数更有用. (3认同)
  • 我认为Limit在Oracle中使用,而不是在SQL Server中使用 (2认同)

Win*_*ith 9

您可以使用:

SELECT COUNT(1) FROM MyTable WHERE ... 
Run Code Online (Sandbox Code Playgroud)

要么

WHERE [NOT] EXISTS 
( SELECT 1 FROM MyTable WHERE ... )
Run Code Online (Sandbox Code Playgroud)

这比SELECT *你只是为每一行选择值1而不是所有字段更有效.

COUNT(*)和COUNT(列名)之间也存在细微差别:

  • COUNT(*) 将计算所有行,包括空值
  • COUNT(column name)将仅计算列名称的非空出现次数

  • *"任何其他东西都有可能产生误导,并且在从DB2迁移到MySQL时可能会发生巨大变化"*在移动DBMS时,您更有可能因为SELECT COUNT(*)的性能下降而被咬住而不是实现差异SELECT 1或COUNT(1).我坚信编写最清楚地表达你想要实现的代码的代码,而不是依赖优化器或编译器来默认你想要的行为. (3认同)
  • 您错误地假设DBMS将以某种方式检查所有这些列。count(1)和count(*)之间的性能差异仅在最死脑筋的DBMS中有所不同。 (2认同)
  • 不,我说_you_实际上依赖于实现细节,当你说它会更有效率.如果您确实希望确保获得最佳性能,则应使用代表性数据对其进行分析,或者完全忘记它.其他任何东西都可能具有误导性,并且在从DB2迁移到MySQL时可能会发生巨大变化. (2认同)
  • 误导性陈述“COUNT(*)”的意思是“计算行数”句号。它不需要访问任何特定列。在大多数情况下,甚至不需要访问行本身,因为任何唯一索引就足够了。 (2认同)

小智 9

SELECT COUNT(1) FROM MyTable WHERE ...
Run Code Online (Sandbox Code Playgroud)

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

我会用

SELECT TOP 1 * FROM MyTable WHERE ...
Run Code Online (Sandbox Code Playgroud)

找到1条记录后,它将终止循环.

  • PS:确定我总是`如果存在(选择TOP 1 1 FROM ... WHERE ..)` (3认同)

小智 7

您可以使用:

SELECT 1 FROM MyTable WHERE... LIMIT 1
Run Code Online (Sandbox Code Playgroud)

使用select 1以避免不必要的字段的检查.

使用LIMIT 1 以避免不必要的行的检查.

  • 好点,但 Limit 适用于 MySQL 和 PostgreSQL,top 适用于 SQL Server,您应该在答案中注明 (5认同)