|
Программирование >> Sql: полное руководство
Стандарт SQLl и большинство коммерческих СУБД предоставляют весьма ограниченные возможности для манипулирования записями и группами записей. SQLl допускает только добавление записей в таблицы, а также их выборку, обновление или удаление (с помощью инструкций select, update и delete). А вот стандарт SQL2 продвинулся в этом направлении гораздо дальше. Он допускает использование записей в SQL-выражениях практически наравне со скалярными значениями. В нем предусмотрен специальный синтаксис для формирования строк данных. Он допускает существование подчиненных запросов, возвращающих записи. И кроме того, он определяет правила обработки записей в операторах сравнения и прочих ситуациях. Конструктор записи В стандарт SQL2 включена специальная конструкция, предназначенная для определения строк данных, - конструктор записи (рис. 9.13). В своей наиболее распространенной форме это просто разделенный запятыми список литералов или скалярных выражений. Вот, например, конструктор для строки данных, структура которой соответствует структуре таблицы offices; (23, San Diego, Western, NULL, DEFAULT, 0.00) скалярнов выражение -- NULL- -DEFAULT --J- . скалярное выражение - - NULL- -DEFAULT- - подчиненный запрос, возвращающий запись - Нарамма конструк! Рис. 9.13. Результатом этого выражения является одна строка данных с шестью столбцами. Четвертый столбец результирующей строки должен содержать значение null. Ключевое слово default в пятой позиции указывает на то, что пятый столбец должен содержать значение, присваиваемое этому столбцу по умолчанию. Названное ключевое слово может встречаться только в определенных ситуациях - например, когда конструктор записи включается в инструкцию insert, вследствие чего генерируемая им запись добавляется в таблицу. Если конструктор записи находится в предложении where, в нем могут использоваться имена столбцов (в качестве отдельных элементов данных или в составе выражений). Для примера рассмотрим такой запрос: Перечислить номера заказов на изделие ACI41002 с указанием количества единиц товара и суммы сделки. select order num, qty, amount from orders where (mfr, product) = (aci, 41002) При выполнении этого запроса предложение where по очереди применяется к каждой строке таблицы orders. Первый констр) тор в этом предложении (слева от знака равенства) генерирует строку из двух столбцов, содержащую идентификаторы производителя и товара для текущего обрабатываемого заказа. Второй конструктор (справа от знака равенства) генерирует строку из двух столбцов, содержащую лите-рально заданные идентификатор производителя ACI и идентификатор товара 41002. Далее оператор = сравнивает две записи (заметьте, не скалярные значения!). Стандартом SQL2 определено, что оператор сравнения записей по очереди сравнивает пары значений каждого столбца. Результатом сравнения является значение true только в том случае, если все попарные сравнения вернули true. Конечно, тот же запрос можно написать и без конструкторов: select order num, qty, amount from orders where (mfr = aci) and (product = 41002) Для такого простого примера обе формы запроса одинаково удобны. А вот в случае более сложных запросов роль конструкторов записей очень важна, особенно когда в сравнении участвует результат подчиненного запроса Подчиненные запросы, возвращающие записи Как уже говорилось ранее в этой главе, стандарт SQL1 предусматривает возможность формулирования достаточно сложных запросов к базе данных с использованием механизма подчиненных запросов. Подчиненный запрос - это обычный запрос на выборку (т.е. инструкция select), но стандарт SQLl требует, чтобы он возвращал скалярное значение, т.е. только одно значениец.шных. Это значение участвует в одном из выражений в главной инструкции SQL, содержащей подчиненный запрос. Такая методика использования подчиненных запросов поддерживается всеми ведущими современными СУБД масштаба предприятия. Стандарт SQL2 значительно расширяет возможности подчиненных запросов: теперь они могут генерировать не только одиночные значения, но и записи, которые могут участвовать в выражениях и сравниваться с другими записями. Для примера предположим, что нам требуется узнать номера и даты заказов самого дорогого товара. Логично начать с написания запроса, который находит идентификатор этого товара и его производителя: Найти идентификатор самого дорогого товара и идентификатор его производителя. select mfr id, proddct id from products where price = (select max(price) from products) Если предположить, что в базе данных есть лишь один самый дорогой товар, Тогда этот запрос сгенерирует одну строку данных, состоящую из двух столбцов. Далее, согласно стандарту SQL2, мы встраиваем наш запрос в качестве подчиненного в запрос, извлекающий из базы данных информацию о заказах на найденный товар. Вывести номера и даты заказов самого дорогого товара. SELECT ORDER NUM, ORDER DATE FROM ORDERS WHERE (MFR, PRODUCT) = (SELECT MFR ID, PRODUCT ID FROM PRODUCTS WHERE PRICE = (SELECT MAX(PRICE) FROM PRODUCTS)) Предложение where на самом верхнем уровне содержит оператор сравнения записей. Слева от него стоит конструктор записи, в котором указаны имена дву> столбцов. Каждый раз, когда проверяется это предложение, конструктор генерирует строку, состоящую из идентификатора производителя и идентификатора товара и; текущей записи таблицы orders. Справа от знака равенства стоит подчиненный запрос, который находит идентификационные данные для самого дорогого товара Результатом этого запроса тоже является строка, состоящая из двух столбцов с теми же типами данных, что и в строке слева от знака равенства. Тот же запрос можно сформулировать и без помощи подчиненного запроса, возвращающего запись, но результат получится гораздо более громоздким: SELECT ORDER NUM, ORDER DATE FROM ORDERS WHERE (MFR = (SELECT MFR ID FROM PRODUCTS WHERE PRICE = (SELECT MAX(PRICE) FROM PRODUCTS)) ) AND (PRODUCT = (SELECT PRODUCT ID FROM PRODUCTS WHERE PRICE = (SELECT MAX(PRICE) FROM PRODUCTS))) Вместо сравнения одной пары записей в предложении where нам пришлось выполнить два отдельных скалярных сравнения: одно - для идентификаторов производителей, а другое - для идентификаторов товаров. Из-за этого пришлось дважды выполнять практически один и тот же подчиненный запрос. Стоит ли говорить о том, что запрос с обработкой записей формулируется гораздо естественнее? Сравнение записей Чаще всего вьфзжения, генерирующие записи, используются в предложениях where и having в операции проверки на равенство, как в нескольких последних примерах. Сгенерированная запись (содержащая значения столбцов из строки, претендующей на включение в результаты запроса) сравнивается с другой записью (обычно с результатом подчиненного запроса или набором литеральных значений), и если эти записи совпадают, запись-кандидат включается в таблицу результатов запроса. Стандартом SQL2 предусмотрены и другие возможности сравнения записей: на неравенство и принадлежность определенному диапазону. При сравнении записей на неравенство в SQL2 используются те же правила, что и при обычной сортировке записей. Сначала сравнивавэтся первые столбцы двух записей, в случае их неравенства они используются для определения порядка записей. Если же они равны, сравниваются вторые столбцы двух записей и т.д. Вот результаты сравнения нескольких записей, составленных из трех столбцов, взятых из таблицы orders: (ACI, 41002, 54) < (REI, 2A44R, 5) - сортировка по первому столбцу
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |