В сервер 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 поддерживает многотабличные удаления - эту функцию можно использовать для эффективного удаления строк как из одной таблицы, так и из нескольких одновременно