为啥要在 MySQL 中使用 EXISTS() 函数?

Posted

技术标签:

【中文标题】为啥要在 MySQL 中使用 EXISTS() 函数?【英文标题】:Why should I use EXISTS() function in MySQL?为什么要在 MySQL 中使用 EXISTS() 函数? 【发布时间】:2016-05-25 13:53:47 【问题描述】:

我有这个问题:

SELECT * FROM mytable t1
  WHERE t1.id = :id AND
        EXISTS(SELECT 1 FROM t2 WHERE t2.post_id = :id)

当我删除 EXISTS() 函数时,我的代码仍然有效:

SELECT * FROM mytable t1
  WHERE t1.id = :id AND
        (SELECT 1 FROM t2 WHERE t2.post_id = :id LIMIT 1)

那我为什么要写这个?它有什么优势?

【问题讨论】:

Exists 在第一次匹配时返回。子查询检索所有匹配的记录。去阅读手册。 @Pred 感谢您的提示。但是我已经编辑了我的第二个查询,那么现在有什么不同吗? ANSI SQL 合规性是原因之一。 输入EXISTS 会痛,但LIMIT 1 不会? EXISTS 在语义上是正确的。您的第二个查询将在其他 DBMS 上失败,这只是一个不好的做法。如果您不小心没有使用 1 而是使用列名,并且匹配记录包含 NULL 或 0,mysql 会将其强制转换为 FALSE,您的查询将提供错误结果。 您的第二个查询,如SELECT * FROM mytable t1 WHERE t1.id = :id AND 1,这是一个正确的查询。因为1 评估为真 【参考方案1】:

简而言之:

EXISTS 在找到第一个结果时返回,而不是获取所有匹配的记录(因此当有多个匹配条件的记录时效率更高) EXISTS 在语义上是正确的。 当第二个查询中有一个列名而不是1,并且该列包含NULLFALSE0等时,MySQL会隐式将其转换为FALSE,这导致错误的结果。 EXISTS 实际上是由 ANSI 标准定义的,而第二种形式不是。 (第二个查询可能在其他 DBMS 中失败)

额外说明一下,当您使用EXISTS 时,您也可以使用*,因为它会检查是否有匹配的记录,而不是值。

【讨论】:

【参考方案2】:

如果子查询返回任何行,EXISTS 子查询为 TRUE,NOT EXISTS 子查询为 FALSE。

当您使用... (SELECT 1 FROM t2 WHERE t2.post_id = :id LIMIT 1) 时,您要么成功返回1,要么返回NULL,分别视为TrueFalse

Exists 合作更专业,因为:

传统上,EXISTS 子查询以 SELECT * 开头,但它可以以 SELECT 5 或 SELECT column1 或任何其他开头。 MySQL 会忽略此类子查询中的 SELECT 列表,因此没有区别。

返回TrueFalse采用最佳方式。

来自MySQL Dev site的参考

【讨论】:

以上是关于为啥要在 MySQL 中使用 EXISTS() 函数?的主要内容,如果未能解决你的问题,请参考以下文章

Sqoop从本地MySQL导入到Hive为啥要求Sqoop一定要在HDFS中

为啥要删除集合名称时要在集合名称后添加“ s”? [复制]

Java:为啥即使路径完整,使用 file.exists() 也会给出错误值?

为啥这个函子的 operator() 需要尾随 const 修饰符?

为啥要在 didFinishLaunchingWithOptions 中使用 UIApplicationLaunchOptionsRemoteNotificationKey?

为啥 os.path.exists() 会阻止 Windows 命名管道连接?