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] INsubqueryexprможет бытьn-кортежем (указанным с помощью синтаксиса конструктора кортежей), а подзапрос может возвращать строкиn-кортежей. Разрешенный синтаксис, следовательно, более конкретно выражен какrow_constructor[NOT] INtable_subqueryДля
,exprop{ALL|ANY|SOME}subqueryexprдолжен быть скалярным значением, а подзапрос должен быть подзапросом к столбцу; он не может возвращать строки с несколькими столбцами.
Другими словами, для подзапроса, возвращающего строки
n-кортежей, это поддерживается:(
expr_1, ...,expr_n) [NOT] INtable_subqueryНо это не поддерживается:
(
expr_1, ...,expr_n)op{ALL|ANY|SOME}subqueryПричина поддержки сравнения строк для
IN, но не для других, заключается в том, чтоINреализуется путем переписывания его как последовательности сравнений=и операцийAND. Этот подход не может использоваться дляALL,ANYилиSOME. -
MySQL не поддерживает
LIMITв подзапросах для определённых операторов подзапросов:mysql>
SELECT * FROM t1WHERE 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()может выполняться различное количество раз для разных выполнений заданного запроса в зависимости от того, как оптимизатор решит его обработать.Для репликации на основе операторов или смешанной репликации одним из последствий этой недетерминированности является то, что такой запрос может давать разные результаты на источнике и его репликах.
© 2025 Oracle
Licensed under the GPLv2 License.