В сервер MySQL поддерживает вложенные запросы вида INSERT ... SELECT ...
и REPLACE ... SELECT ...
. В других контекстах можно использовать
и функцию IN()
.
Вложенные операции выборки реализованы в версии 4.1.
Между тем, во многих случаях можно переписать запрос, чтобы не использовать вложенную выборку. Например, запрос:
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
можно переписать следующим образом:
SELECT table1.* FROM table1,table2 WHERE table1.id=table2.id;
Запросы:
SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2); SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2 WHERE table1.id=table2.id);
эквивалентны следующему:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;
Для более сложных подзапросов часто можно создать временные таблицы,
содержащие данный подзапрос. Иногда, однако, этот способ не годится, чаще
всего для команд DELETE
, для которых в стандарте SQL не поддерживаются
объединения (за исключением вложенных выборок). В этой ситуации возможны
два временных (пока вложенные запросы не поддерживаются сервером MySQL)
варианта решения проблемы.
Первый вариант следующий: при помощи какого-либо
процедурно-ориентированного языка программирования (такого как Perl или
PHP) делается запрос SELECT
для получения первичных ключей тех записей,
которые должны быть удалены, а затем полученные величины используются для
составления команды DELETE (DELETE FROM ... WHERE ... IN (key1, key2, ...))
.
Второй вариант предполагает применение диалогового SQL для автоматического
создания набора команд DELETE
с использованием расширения MySQL CONCAT()
(вместо стандартного оператора ||
). Например:
SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', "'", tab1.pkid, "'", ';') FROM tab1, tab2 WHERE tab1.col1 = tab2.col2;
Можно поместить этот запрос в файл скрипта, перенаправить стандартный вход клиента командной строки с этого файла, а стандартный выход - на еще один экземпляр клиента командной строки:
shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb
Сервер версии MySQL 4.0 поддерживает многотабличные удаления - эту функцию можно использовать для эффективного удаления строк как из одной таблицы, так и из нескольких одновременно