通常,您不能修改表并从子查询中的同一个表中进行选择。例如,此限制适用于以下形式的语句:
DELETE FROM t WHERE ... (SELECT ... FROM t ...); UPDATE t ... WHERE col = (SELECT ... FROM t ...); {INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
例外:如果您正在使用派生表修改表并且该派生表是物化的而不是合并到外部查询中,则上述禁令不适用。例子:
UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);
这里派生表的结果具体化为临时表,因此在 更新发生
t
时已经选择了相关行。t
仅部分支持行比较操作:
对于, 可以是一个 元组(使用行构造函数语法指定)并且子查询可以返回元组的行 。因此,允许的语法更具体地表示为
expr
[NOT] INsubquery
expr
n
n
row_constructor
[NOT] INtable_subquery
对于, 必须是标量值且子查询必须是列子查询;它不能返回多列行。
expr
op
{ALL|ANY|SOME}subquery
expr
换句话说,对于返回元组行的子查询
n
,这是受支持的:(expr_1, ..., expr_n) [NOT] IN table_subquery
但这不受支持:
(expr_1, ..., expr_n) op {ALL|ANY|SOME} subquery
支持行比较
IN
但不支持其他 行比较的原因IN
是通过将其重写为一系列=
比较和AND
操作来实现的。此方法不能用于ALL
、ANY
或SOME
。子句中的子查询
FROM
不能是关联子查询。它们在查询执行期间被整体具体化(评估以产生结果集),因此不能对外部查询的每一行进行评估。在 MySQL 5.6.3 之前,物化发生在评估外部查询之前。从 5.6.3 开始,优化器延迟实现直到需要结果,这可能允许避免实现。请参阅 第 8.2.2.4 节,“优化派生表”。MySQL 不支持
LIMIT
某些子查询运算符的子查询:mysql> SELECT * FROM t1 WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1); ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
MySQL 允许子查询引用具有数据修改副作用的存储函数,例如将行插入表中。例如,如果
f()
插入行,则以下查询可以修改数据:SELECT ... WHERE x IN (SELECT f() ...);
此行为是对 SQL 标准的扩展。在 MySQL 中,它可能会产生不确定的结果,因为
f()
对于给定查询的不同执行,它可能会执行不同的次数,具体取决于优化器选择如何处理它。对于基于语句或混合格式的复制,这种不确定性的一个含义是这样的查询可以在源及其从属上产生不同的结果。
在 MySQL 5.6.3 之前,
FROM
子句中的子查询是通过将结果具体化到一个临时表中来计算的,这个表不使用索引。从 5.6.3 开始,优化器会在物化表上创建一个索引,如果这会导致更快的查询执行。请参阅第 8.2.2.4 节,“优化派生表”。