Spec-Zone.ru › MySQL 9.2

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

  • 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() может выполняться различное количество раз для разных выполнений заданного запроса в зависимости от того, как оптимизатор решит его обработать.

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

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

Spec-Zone.ru

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