Spec-Zone.ru › MySQL 5.7

13.2.10.12 Ограничения на подзапросы

  • В общем случае, вы не можете изменять таблицу и одновременно выбирать из той же таблицы в подзапросе. Например, это ограничение применяется к операторам следующих форм:

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

    Исключение: это ограничение не применяется, если для изменяемой таблицы используется производная таблица, и эта производная таблица материализуется, а не объединяется с внешним запросом. (См. раздел 8.2.2.4, «Оптимизация производных таблиц и ссылок на представления с помощью объединения или материализации».) Пример:

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

    Здесь результат из производной таблицы материализуется как временная таблица, поэтому соответствующие строки в t уже были выбраны к моменту обновления t.

  • Операции сравнения строк частично поддерживаются:

    • Для expr [NOT] IN subquery, expr может быть n-кортежем (указанным с помощью синтаксиса конструктора строк), а подзапрос может возвращать строки n-кортежей. Поэтому допустимый синтаксис более точно выражается как row_constructor [NOT] IN table_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 не могут быть связанными подзапросами. Они материализуются целиком (вычисляются для получения набора результатов) во время выполнения запроса, поэтому они не могут быть вычислены для каждой строки внешнего запроса. Оптимизатор откладывает материализацию до тех пор, пока результат не потребуется, что может позволить избежать материализации. См. раздел 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 does not yet support
     'LIMIT & IN/ALL/ANY/SOME subquery'
    
  • MySQL разрешает подзапросу ссылаться на хранимую функцию, которая имеет побочные эффекты изменения данных, такие как вставка строк в таблицу. Например, если f() вставляет строки, следующий запрос может изменять данные:

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

    Это поведение является расширением стандарта SQL. В MySQL это может привести к недетерминированным результатам, поскольку f() может быть выполнен разное количество раз для разных выполнений данного запроса в зависимости от того, как оптимизатор решит его обработать.

    Для репликации на основе операторов или смешанной репликации одним из последствий этой недетерминированности является то, что такой запрос может давать разные результаты на источнике и его репликах.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/subquery-restrictions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API