文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  子查询限制

15.2.15.12 子查询限制

  • 通常,您不能在子查询中修改表并从同一表中选择数据。例如,此限制适用于以下形式的语句

    DELETE FROM t WHERE ... (SELECT ... FROM t ...);
    UPDATE t ... WHERE col = (SELECT ... FROM t ...);
    {INSERT|REPLACE} INTO t (SELECT ... FROM t ...);

    例外:如果对于要修改的表,您使用的是派生表,并且该派生表是物化的而不是合并到外部查询中的,则上述禁止不适用。(见 第 10.2.2.4 节,“优化派生表、视图引用和公用表表达式,使用合并或物化”。)示例

    UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS dt ...);

    在这里,派生表的结果被物化为一个临时表,因此在对 t 进行更新之前,已经从 t 中选择了相关行。

    一般来说,您可以通过添加一个 NO_MERGE 优化提示来影响优化器对派生表的物化。见 第 10.9.3 节,“优化提示”

  • 行比较操作仅部分支持

    • 对于 expr [NOT] IN subqueryexpr 可以是 n 元组(使用行构造语法指定),子查询可以返回 n 元组的行。因此,允许的语法更具体地表示为 row_constructor [NOT] IN table_subquery

    • 对于 expr op {ALL|ANY|SOME} subqueryexpr 必须是标量值,子查询必须是列子查询;它不能返回多列行。

    换句话说,对于返回 n 元组行的子查询,这是支持的

    (expr_1, ..., expr_n) [NOT] IN table_subquery

    但这不是支持的

    (expr_1, ..., expr_n) op {ALL|ANY|SOME} subquery

    支持 IN 的行比较而其他比较不支持的原因是 IN 是通过将其重写为一系列 = 比较和 AND 操作来实现的。这种方法不能用于 ALLANYSOME

  • 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'

    参见 第 15.2.15.10 节,“子查询错误”

  • MySQL 允许子查询引用具有数据修改副作用的存储函数,例如将行插入表中。例如,如果 f() 插入行,则以下查询可以修改数据

    SELECT ... WHERE x IN (SELECT f() ...);

    此行为是对 SQL 标准的扩展。在 MySQL 中,它可能会产生非确定性结果,因为 f() 可能会针对给定查询的不同执行执行不同的次数,具体取决于优化器如何选择处理它。

    对于基于语句或混合格式的复制,这种不确定性带来的一个影响是,此类查询可能会在源和它的副本上产生不同的结果。