Вложенный запрос – это запрос, который находится внутри другого SQL запроса и встроен внутри условного оператора WHERE.
Данный вид запросов используется для возвращения данных, которые будут использоваться в основном запросе, как условие для ограничения получаемых данных.
Вложенные запросы должны следовать следующим правилам:
- Вложенный запрос должен быть заключён в родительский запрос.
- Вложенный запрос может содержать только одну колонку в операторе SELECT.
- Оператор ORDER BY не может быть использован во вложенном запросе. Для обеспечения функционала ORDER BY, во вложенном запросе может быть использован GROUP BY.
- Вложенные запросы, возвращающие более одной записи могут использоваться с операторами нескольких значений, как оператор IN.
- Вложенный запрос не может заканчиваться в функции.
- SELECT не может включать никаких ссылок на значения BLOB, ARRAY, CLOB и NCLOB.
- Оператор BETWEEN не может быть использован вместе с вложенным запросом.
Примеры:
Вложенный запрос имеет следующий вид:
SELECT имя_колонки [, имя_колонки2 ]
FROM таблица1 [, таблица2 ]
WHERE имя_колонки ОПЕРАТОР
(SELECT имя_колонки [, имя_колонки2 ]
FROM таблица1 [, таблица2 ]
[WHERE])
Предположим, что у нас есть таблица developers, которая содержит следующие записи:
+----+-------------------+-----------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------------+-----------+------------+--------+
| 1 | Eugene Suleimanov | Java | 2 | 2500 |
| 2 | Peter Romanenko | Java | 3 | 3500 |
| 3 | Andrei Komarov | C++ | 3 | 2500 |
| 4 | Konstantin Geiko | C# | 2 | 2000 |
| 5 | Asya Suleimanova | UI/UX | 2 | 1800 |
| 6 | Ludmila Geiko | UI/UX | 2 | 1800 |
| 7 | Ivan Ivanov | C# | 1 | 900 |
+----+-------------------+-----------+------------+--------+
Попробуем выполнить следующий вложенный запрос:
SELECT * FROM developers
WHERE ID IN (SELECT ID
FROM developers
WHERE SALARY > 2000);
Предположим, что у нас есть клон таблицы developers, который имеет имя developers_clone и имеет следующую структуру:
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| ID | int(11) | NO | PRI | NULL | |
| NAME | varchar(100) | NO | | NULL | |
| SPECIALTY | varchar(100) | YES | | NULL | |
| EXPERIENCE | int(11) | NO | | NULL | |
| SALARY | int(11) | YES | | NULL | |
+------------+--------------+------+-----+---------+-------+
И не содержит данных:
mysql> SELECT * FROM developers_clone;
Empty set (0.00 sec)
Теперь попробуем выполнить для этой же таблицы следующий запрос:
mysql> INSERT INTO developers_clone
SELECT * FROM developers
WHERE ID IN (SELECT ID
FROM developers);
В результате выполнения данного запроса таблица developers_clone будет содержать следующие данные:
+----+-------------------+-----------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------------+-----------+------------+--------+
| 1 | Eugene Suleimanov | Java | 2 | 2500 |
| 2 | Peter Romanenko | Java | 3 | 3500 |
| 3 | Andrei Komarov | C++ | 3 | 2500 |
| 4 | Konstantin Geiko | C# | 2 | 2000 |
| 5 | Asya Suleimanova | UI/UX | 2 | 1800 |
| 6 | Ludmila Geiko | UI/UX | 2 | 1800 |
| 7 | Ivan Ivanov | C# | 1 | 900 |
+----+-------------------+-----------+------------+--------+
Другими словами, мы скопировали все данные из таблицы developers в таблицу developers_clone.
Теперь мы изменим данные в таблице developers воспользовавшись данными из таблицы developers_clone с помощью следующего запроса:
mysql> UPDATE developers
SET SALARY = SALARY * 1.25
WHERE EXPERIENCE IN (SELECT EXPERIENCE
FROM developers_clone
WHERE EXPERIENCE >=2);
В результате этого наша таблица содержащая изначальные данные:
+----+-------------------+-----------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------------+-----------+------------+--------+
| 1 | Eugene Suleimanov | Java | 2 | 2500 |
| 2 | Peter Romanenko | Java | 3 | 3500 |
| 3 | Andrei Komarov | C++ | 3 | 2500 |
| 4 | Konstantin Geiko | C# | 2 | 2000 |
| 5 | Asya Suleimanova | UI/UX | 2 | 1800 |
| 6 | Ludmila Geiko | UI/UX | 2 | 1800 |
| 7 | Ivan Ivanov | C# | 1 | 900 |
+----+-------------------+-----------+------------+--------+
Будет хранить следующие данные:
+----+-------------------+-----------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------------+-----------+------------+--------+
| 1 | Eugene Suleimanov | Java | 2 | 3125 |
| 2 | Peter Romanenko | Java | 3 | 4375 |
| 3 | Andrei Komarov | C++ | 3 | 3125 |
| 4 | Konstantin Geiko | C# | 2 | 2500 |
| 5 | Asya Suleimanova | UI/UX | 2 | 2250 |
| 6 | Ludmila Geiko | UI/UX | 2 | 2250 |
| 7 | Ivan Ivanov | C# | 1 | 900 |
+----+-------------------+-----------+------------+--------+
И наконец, попробуем выполнить удаление данных из таблицы с помощью вложенного запроса:
mysql> DELETE FROM developers
WHERE EXPERIENCE IN (SELECT EXPERIENCE FROM developers_clone
WHERE EXPERIENCE >= 2);
В результате таблица developers содерит следующие записи:
+----+-------------+-----------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------+-----------+------------+--------+
| 7 | Ivan Ivanov | C# | 1 | 900 |
+----+-------------+-----------+------------+--------+
Очистим таблицу developers:
mysql> TRUNCATE developers;
Таблица пуста:
mysql> SELECT * FROM developers;
Empty set (0.00 sec)
Теперь восстановим данные таблицы developers, с помощью резервной таблицы developers_clone используя следующий запрос:
mysql> INSERT INTO developers
SELECT * FROM developers_clone
WHERE ID IN (SELECT ID
FROM developers_clone);
Наша таблица developers имеет исходный вид:
mysql> SELECT * FROM developers;
+----+-------------------+-----------+------------+--------+
| ID | NAME | SPECIALTY | EXPERIENCE | SALARY |
+----+-------------------+-----------+------------+--------+
| 1 | Eugene Suleimanov | Java | 2 | 2500 |
| 2 | Peter Romanenko | Java | 3 | 3500 |
| 3 | Andrei Komarov | C++ | 3 | 2500 |
| 4 | Konstantin Geiko | C# | 2 | 2000 |
| 5 | Asya Suleimanova | UI/UX | 2 | 1800 |
| 6 | Ludmila Geiko | UI/UX | 2 | 1800 |
| 7 | Ivan Ivanov | C# | 1 | 900 |
+----+-------------------+-----------+------------+--------+
7 rows in set (0.00 sec)
На этом мы заканчиваем изучение вложенных запросов.
В следующей статье мы рассмотрим использование последовательностей.