- •4. Дополнительные средства языка sql субд Oracle
- •4.1. Операторы объединения
- •4.2. Подзапросы (вложенные запросы)
- •Однострочные подзапросы
- •Многострочные подзапросы
- •Подзапросы, возвращающие более одного столбца
- •4.3. Перенос данных между таблицами
- •Перенос данных с помощью оператора insert
- •Создание новой таблицы на основе уже существующей
- •4.4. Переименование таблиц
- •4.6. Представления
- •Создание представления
- •Удаление представлений
- •Изменение определения представления
- •Анализ первых n записей
- •4.7. Другие объекты базы данных Последовательности
- •Синонимы
- •Словарь данных Oracle
4.2. Подзапросы (вложенные запросы)
Подзапрос — это обычный запрос SELECT, вложенный в оператор SELECT, UPDATE или DELETE. Он используется в качестве источника данных для раздела FROM или WHERE родительского оператора.
Подзапрос может содержать внутри себя другие подзапросы. В документации Oracle утверждается, что число уровней вложения не ограничено. "Не ограничено" обычно следует интерпретировать как "зависит от количества доступных ресурсов компьютера, но в любом случае это наверняка больше, чем вам когда-либо потребуется".
Подзапрос применяется в тех случаях, когда для выполнения одного запроса требуется предварительно выполнить другой. Например, чтобы определить, какие товары продаются лучше, чем в среднем, нужно сначала найти это "среднее". Чтобы выяснить, сколько денег заработал старший продавец, нужно знать, кто является старшим продавцом. Чтобы установить, какие товары продаются хуже, чем в прошлом году, нужно знать, как они продавались год назад. Во всех этих ситуациях необходимая информация может быть получена с помощью подзапроса.
Однострочные подзапросы
Что получить все сведения о товарах с наименованием "Small Widget", поступивших в день последнего пополнения запасов этого товара, можно воспользоваться следующим оператором SELECT, содержащим подзапрос:
SELECT * FROM product
WHERE last_stock_date = (
SELECT last_stock_date FROM product
WHERE product_name = 'Small Widget'
) ;
Ключевой характеристикой такого подзапроса является то, что он возвращает единственное значение. Например, подзапрос для определения даты последнего пополнения запасов Small Widget, может возвратить только одно значение, поскольку для хранения этой даты в таблице товаров отведен только один столбец. В этом случае в условии поиска предложения WHERE внешнего оператора можно уверенно ставить знак равенства. Если бы подзапрос потенциально мог возвращать несколько значений, знак равенства нельзя было бы использовать, поскольку дата последнего пополнения запасов во внешнем операторе всегда имеет только одно значение.
Подзапрос такого типа называется однострочным подзапросом (single-row subquery), поскольку он может возвращать только одну строку результатов. Внешний оператор может возвращать любое число строк на основе одного ответа подзапроса.
Подзапрос и внешний оператор могут ссылаться на совершенно разные таблицы. Допустим, нужно узнать обо всех продажах, которые выполнил Гари Андерсон. Известно только имя продавца, но не код, под которым он значится в таблице покупок. Следовательно, нужно сделать так, чтобы оператор SELECT сам нашел код Гари Андерсона, а потом показал записи о его продажах:
SELECT * FROM purchase
WHERE salesperson = (
SELECT person_code
FROM person
WHERE first_name = 'Gary' AND last_name = 'Anderson' ) ;
Получить список самых дорогих товаров можно с помощью подзапроса, определяющего среднюю цену товара:
SELECT * FROM product
WHERE product_price > (
SELECT AVG(product_price)
FROM product ) ;
Многострочные подзапросы
Многострочный подзапрос (multirow subquery) — это подзапрос, который может возвращать более одной строки результатов. Для таких подзапросов нельзя выполнять сравнение с помощью знака равенства; необходимо использовать операцию IN.
Например, чтобы узнать, какие товары не продаются, можно получить с помощью подзапроса список всех названий товаров из таблицы покупок, а затем передать его внешнему оператору, чтобы исключить записи об этих товарах из выходных данных:
SELECT * FROM product
WHERE product_name NOT IN (
SELECT DISTINCT product_name
FROM purchase
)
ORDER BY product_name ;
Если поступило распоряжение снизить на 10% цены всех товаров, не пользующихся спросом, то это можно сделать единственной командой UPDATE, поместив в ее предложение WHERE подзапрос, определяющий, какие товары не продавались:
UPDATE product
SET product_price = product_price * 0.9
WHERE product_name NOT IN (
SELECT DISTINCT product_name
FROM purchase
) ;
