Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Restrictions on Subqueries

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 ...);

    例外:如果您使用的是派生表,并且该派生表被materialized,而不是合并到外部查询中。 (见第10.2.2.4节,“Optimizing Derived Tables, View References, and Common Table Expressions with Merging or Materialization”。) 示例:

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

    在这里,派生表的结果被materialized为一个临时表,所以在更新t时,相关的行已经被选择了。

    一般来说,您可以通过添加NO_MERGE优化器提示来影响优化器,使派生表materialized。见第10.9.3节,“Optimizer Hints”

  • 行比较操作只部分支持:

    • 对于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由重写为一个序列的=比较和AND操作实现的。这approach不能用于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节,“Subquery Errors”

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

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

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

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