为啥要在 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
,并且该列包含NULL
、FALSE
、0
等时,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
,分别视为True
或False
。
与Exists
合作更专业,因为:
传统上,EXISTS 子查询以 SELECT * 开头,但它可以以 SELECT 5 或 SELECT column1 或任何其他开头。 MySQL 会忽略此类子查询中的 SELECT 列表,因此没有区别。
返回True
或False
采用最佳方式。
来自MySQL Dev site的参考
【讨论】:
以上是关于为啥要在 MySQL 中使用 EXISTS() 函数?的主要内容,如果未能解决你的问题,请参考以下文章
Sqoop从本地MySQL导入到Hive为啥要求Sqoop一定要在HDFS中
Java:为啥即使路径完整,使用 file.exists() 也会给出错误值?
为啥这个函子的 operator() 需要尾随 const 修饰符?
为啥要在 didFinishLaunchingWithOptions 中使用 UIApplicationLaunchOptionsRemoteNotificationKey?