- •Содержание
- •Основные понятия
- •Понятие данных
- •Файловые системы
- •Системы баз данных
- •История развития субд
- •Трехуровневая архитектура ansi/sparc
- •Общая характеристика моделей данных
- •Основные понятия модели данных
- •Представление статических и динамических свойств
- •Общая характеристика структурных компонентов. Множества: домены и атрибуты
- •Общая характеристика структурных компонентов. Отношения: сущности
- •Общая характеристика структурных компонентов. Отношения: связи
- •Общая характеристика ограничений целостности
- •Модель данных «сущность – связь»
- •Уровни представления информации
- •Уровень 1 – информация о сущностях и связях
- •Уровень 2. Структура информации
- •Ограничения целостности в модели сущность-связь
- •Расширенная модель данных сущность-связь: нотация idef1x
- •Реляционная модель данных
- •Базовые структурные компоненты реляционной модели данных
- •Целостная часть реляционной модели данных
- •Языковые средства описания данных
- •Манипуляционная часть реляционной модели данных
- •Подмножество sql для манипулирования данными
- •Примеры написания запросов
- •I. И еще несколько примеров написания запросов из документации [10]
- •Краткая характеристика языка sql pl db2® udb
- •Дополнительные возможности описания ограничений целостности
- •Дополнительные возможности db2
- •Описание данных
- •Манипулирование данными
- •Дополнительные возможности формирования запросов
- •Типы данных, определенные пользователем
- •Функции, определенные пользователем
- •Теория проектирования реляционных баз данных
- •Цели проектирования
- •Функциональные зависимости
- •1. Рефлексивность
- •2. Пополнение
- •3. Транзитивность
- •4. Псевдотранзитивность
- •5. Аддитивность (объединение)
- •6. Декомпозиция (проективность)
- •7. Композиция
- •Нормализация отношений
- •Внутренние структуры хранения
- •Структурная схема обработки запроса
- •Бинарные деревья
- •Многоходовые деревья
- •Сравнение методов индексирования
- •Создание индексов в db2®
- •Организация файлов базы данных в db2®
Подмножество sql для манипулирования данными
Как уже говорилось, языком реляционных СУБД является SQL. Для написания запросов к базе данных в языке SQL предусмотрено специальное предложение SELECT, которое, с одной стороны, реализует все возможности, определяемые реляционным исчислением с переменными-кортежами (а, следовательно, и реляционной алгеброй), а с другой – предоставляет дополнительные возможности, такие как реализация арифметических вычислений и специальных агрегатных функций, применяемых к множеству значений.
В соответствии с этим, сначала рассмотрим правила записи выражений и предикатов, затем – синтаксис предложения SELECT, и завершим данную тему рассмотрением способов реализации различных запросов к базе данных.
Здесь будут рассмотрены наиболее часто используемые возможности предложения SELECT. Полное описание предложения SELECT, со всеми его возможностями, можно найти в SQL Reference [10, 11].
Выражения
Некоторые правила записи выражений были рассмотрены при описании предложения CREATE TABLE ЯОД. Однако в предложении SELECT используются более сложные выражения, поэтому здесь рассматриваются некоторые дополнительные возможности записи выражений.
Выражение определяет значение. Оно может быть простым, представленным только константой или именем колонки, или более сложным. Когда подобные сложные выражения используются часто, можно создать функцию, реализующую это выражение, и использовать ее везде, где требуется использовать выражение.
Как уже говорилось, выражение имеет следующий вид:
операнд [ операция операнд … ]
операнду может предшествовать знак плюс (+) или минус (-).
В качестве операнда могут быть использованы следующие конструкции:
константа
имя_колонки
специальный_регистр
вызов_функции
(выражение)
(скалярный_запрос)
именованная_продолжительность
case-выражение
cast-спецификация
ссылка_на_последовательность
Некоторые из этих конструкций были рассмотрены ранее, в описании подмножества ЯОД SQL. Далее рассматриваются другие способы задания операндов в выражении.
Скалярный запрос
Скалярный запрос, который можно записывать в выражениях, представляется как полная форма предложения SELECT (или запрос), заключенная в круглые скобки. Он должен возвращать результат, содержащий только одну строку, имеющую только одну колонку. Если скалярный запрос не возвращает строку результата, тогда результатом выражения является значение NULL.
Именованная продолжительность
Поскольку в языке нет констант типа даты – времени, вместо них, там, где это нужно, может использоваться именованная продолжительность, рассмотренная при описании CREATE TABLE ЯОД.
case-выражение
Выражение CASE позволяет определить результат на основе проверки одного или нескольких условий.
Выражение CASE может быть записано двумя способами.
Первый способ имеет следующий вид:
CASE WHEN условие_поиска1 THEN выражение1 [WHEN условие_поиска2 THEN выражение2 …]
[ ELSE выражениеL ] END
Вычисление выражения CASE, представленного таким образом, начинается с вычисления условия_поиска1. Если в результате будет получено значение false (ложь), вычисляется условие_поиска2, и т.д. Как только для какого-либо условия_поискаK будет получено значение true (истина), вычисляется связанное с ним выражениеK, определяющее результат вычисления выражения CASE, и на этом вычисления прекращаются. Если все условия поиска дают в результате значение false, результатом выражения CASE будет результат вычисления выраженияL, если присутствует ELSE, или же NULL, если ELSE не указано.
Следует отметить, что если при вычислении какого-либо условия поиска получается неопределенное значение (из-за наличия NULL значений), такое значение не является истинным и интерпретируется как false.
Второй способ записи выражения CASE имеет следующий вид:
CASE выражение WHEN выражение1 THEN результирующее_выражение1 [ WHEN выражение2 THEN результирующее_выражение2 …][ ELSE результирующее_выражениеL ] END
При вычислении выражения CASE, заданного таким способом, результат вычисления выражения последовательно сравнивается с результатами вычисления выражения1, выражения2 и т.д. (в соответствии с этим, тип результата вычисления выражения должен быть сравнимым с типом результатов вычисления выражений, записанных после WHEN). Как только очередное сравнение окажется успешным (выражение = выражениеK), вычисляется соответствующее результирующее_выражениеK, определяющее результат вычисления выражения CASE, и вычисления заканчиваются. Если же значение выражения не совпадает ни с одним из результатов выражений, указанных после WHEN, тогда результатом вычисления выражения CASE является результат вычисления результирующего_выраженияL, если указано ELSE, или NULL, если ELSE отсутствует.
Для обеих форм записи выражения CASE должны выполняться следующие условия:
после ключевых слов THEN и ELSE вместо выражения может быть указано ключевое слово NULL;
по крайней мере, после хотя бы одного THEN не должно быть указано NULL;
результаты всех выражений, записанных после THEN и ELSE, должны иметь совместимый тип данных.
Для обеих форм записи выражения CASE проверки, указанные в выражении, выполняются в порядке их записи.
cast-спецификация
CAST спецификация осуществляет преобразование типа и записывается следующим образом:
CAST( выражение AS тип_данных)
Результатом вычисления CAST является результат вычисления выражения, преобразованный к указанному типу данных. Если в качестве выражения записано NULL, CAST возвращает значение NULL, имеющее указанный тип данных.
Тип_данных – название существующего типа данных. Если тип данных имеет дополнительные атрибуты, например, длина, или точность и масштаб, эти атрибуты должны быть указаны вместе с типом данных.
Ограничения на использование типов данных:
если в качестве операнда указано выражение, тогда допустимый тип данных определяется типом результата выражения (исходного типа данных);
если в качестве операнда указано ключевое слово NULL, тогда можно использовать любой существующий тип данных.
Если числовые данные преобразуются к символьному типу, в результате будет получена строка фиксированной длины. Если символьные данные преобразуются к числовому типу, результат преобразования зависит от заданного числового типа.
Функции
СУБД предоставляет большой набор встроенных функций, возвращающих в качестве результата некоторое (одно) значение. К встроенным функциям относятся операции (например, +), функции преобразования, скалярные функции и агрегатные функции (или функции для колонок).
Рассмотрим некоторые встроенные функции SQL DB2®.
Функции SQL DB2®
Функция представляет собой некоторую операцию, на которую можно ссылаться по имени. За именем функции должны следовать парные круглые скобки, содержащие список аргументов (список аргументов может отсутствовать).
Поддерживаются два типа функций:
встроенные функции поддерживаются менеджером базы данных,
функции, определенные пользователем (UDF – User Defined Functions), создаются с помощью предложения CREATE FUNCTION.
Встроенные функции можно разделить на три типа: агрегатные функции (функции колонок), скалярные функции и табличные функции.
Аргументом агрегатной функции (функции колонки) является совокупность значений одного типа (значения некоторой колонки таблицы). Функция колонки возвращает в качестве результата одно значение (возможно, NULL) и может быть указана в предложениях SQL везде, где может быть использовано выражение.
Аргументами скалярной функции являются отдельные скалярные значения, которые могут относиться к разным типам и иметь разные значения. Скалярная функция возвращает в качестве результата одно значение (возможно, NULL), и может быть указана в предложениях SQL везде, где может быть использовано выражение.
Аргументами табличной функции являются отдельные скалярные значения, которые могут относиться к разным типам данных и иметь разные значения. Табличная функция возвращает в качестве результата таблицу и может быть указана только в конструкции FROM предложения SELECT.
Агрегатные функции
Некоторые агрегатные функции приведены в таблице 4.7.
Таблица 4.7. Агрегатные функции
Функция |
Описание |
AVG |
Возвращает среднее арифметическое для совокупности чисел |
COUNT |
Возвращает количество строк или значений в совокупности строк или значений |
COUNT_BIG |
Возвращает количество строк или значений в совокупности строк или значений. Результат может превышать максимальное значение, представимое типом INTEGER. |
MAX |
Возвращает максимальное значение из множества значений |
MIN |
Возвращает минимальное значение из множества значений |
STDDEV |
Возвращает среднеквадратичное отклонение для множества чисел |
SUM |
Возвращает сумму чисел из множества чисел |
VARIANCE |
Возвращает дисперсию для множества чисел |
Общий синтаксис этих функций:
имя_функции([ALL | DISTINCT] выражение)
Все функции, вызов которых соответствует приведенной схеме, игнорируют пустые (NULL) значения в колонке; если указано DISTINCT, избыточные дублирующие значения удаляются. Если аргументом функции является пустое множество значений, все функции, кроме COUNT и COUNT_BIG, возвращают значение NULL; указанные функции возвращают значение 0.
Функции COUNT и COUNT_BIG имеют еще одну форму записи:
имя_функции (*)
Данные функции не игнорируют пустые (NULL) значения.
Аргументы функций AVG, SUM, STDEV, VARIANCE должны быть числовыми (только встроенных типов данных).
Функции COUNT и COUNT_BIG возвращают целое значение; STDEV и VARIANCE – вещественное значение двойной точности; тип результата остальных функций определяется типом аргумента.
Скалярные функции преобразования типа
Некоторые скалярные функции преобразования типа приведены в таблице 4.8.
Таблица 4.8. Функции преобразования типа
Функция |
Описание |
BIGINT( выражение ) |
Возвращает 64-х битное целое представление числа или символьной строки, содержащей представление целой константы |
CHR( выражение ) |
Возвращает CHARACTER представление значения |
DATE( выражение ) |
Возвращает DATE из значения. Аргументом функции может быть дата, временная метка, целое положительное, не превышающее 3652059, или корректное строковое представление даты или временной метки. |
DECIMAL ( выражение [ точность [, масштаб ]]) |
Возвращает DECIMAL представление значения, представленного числом или символьной строкой, содержащей представление числовой константы |
DOUBLE ( выражение ) |
Возвращает DOUBLE PRECISION представление числа или символьной строки, содержащей представление числовой константы |
FLOAT ( выражение ) |
Возвращает FLOAT представление числа или символьной строки, содержащей представление числовой константы |
INTEGER ( выражение ) |
Возвращает INTEGER представление числа или символьной строки, содержащей представление целой константы |
REAL ( выражение ) |
Возвращает REAL представление числа или символьной строки, содержащей представление числовой константы |
SMALLINT ( выражение ) |
Возвращает SMALLINT представление числа или символьной строки, содержащей представление целой константы |
TIME ( выражение ) |
Возвращает TIME из значения. Аргументом функции может быть время, временная метка или корректное строковое представление времени или временной метки. |
TIMESTAMP ( выражение1 [ , выражение2 ] ) |
Возвращает TIMESTAMP из значения или пары значений. Если в функции указан только один аргумент, он может быть задан как временная метка или корректное строковое представление временной метки. Если указаны два аргумента, тогда выражение1 задает дату или строковое представление даты, выражение2 – время или строковое представление времени |
VARCHAR ( выражение [, целое ]) |
Возвращает VARCHAR представление значения; целое определяет максимальную длину строки |
Скалярные функции даты – времени
Некоторые скалярные функции даты – времени приведены в таблице 4.9.
Таблица 4.9. Скалярные функции даты – времени
Функция |
Описание |
DAY ( дата ) |
Возвращает часть, соответствующая дню, из значения аргумента |
DAYNAME ( дата ) |
Возвращает символьную строку, содержащую название дня недели (например, Friday) для части аргумента, соответствующей дню |
DAYOFWEEK ( дата ) |
Возвращает числовое значение дня недели для значения аргумента, где 1 соответствует воскресенью и 7 соответствует субботе |
DAYOFWEEK_ISO ( дата ) |
Возвращает числовое значение дня недели для значения аргумента, где 1 соответствует понедельнику и 7 соответствует воскресенью |
DAYOFYEAR ( дата ) |
Возвращает день года из значения аргумента |
DAYS ( дата ) |
Возвращает целое представление даты для значения аргумента |
HOUR ( дата ) |
Возвращает часть значения аргумента, соответствующую часам |
JULIAN_DAY ( дата ) |
Возвращает целое значение, соответствующее количеству дней от January 1, 4712 B.C. до даты, заданной аргументом |
MICROSECOND ( дата ) |
Возвращает часть значения аргумента, соответствующую микросекундам |
MIDNIGHT_SECONDS ( дата ) |
Возвращает целое значение, представляющее количество секунд между полуночью и указанным аргументом значением времени |
MINUTE ( дата ) |
Возвращает часть значения аргумента, соответствующую минутам |
MONTH ( дата ) |
Возвращает часть значения, соответствующую месяцу |
MONTHNAME ( дата ) |
Возвращает символьную строку, соответствующую названию месяца (например, January) для части аргумента, представляющего дату или временную метку, соответствующей месяцу, на основе locale, который имел место в момент старта базы данных |
QUARTER ( дата ) |
Возвращает целое, соответствующее кварталу года, к которому относится дата |
SECOND ( дата ) |
Возвращает часть значения, соответствующую секундам |
TIMESTAMP_FORMAT ( строка , формат ) |
Возвращает временную метку для символьной строки (аргумент 1), которая интерпретируется в соответствии с шаблоном формата (аргумент 2). |
TIMESTAMP_ISO ( дата ) |
Возвращает значение временной метки на основе аргумента, заданного в виде даты, времени или временной метки. Если аргумент представляет дату, в значении временной метки все элементы, соответствующие времени, устанавливаются в нули. Если аргумент представляет время, в поля временной метки, соответствующие дате, вставляется значение CURRENT DATE, а поле дробной части времени устанавливается в нуль. |
TO_CHAR ( временная_метка , формат ) |
Возвращает символьное представление временной метки |
TO_DATE ( строка , формат) |
Возвращает значение временной метки из строки |
VARCHAR_FORMAT ( временная_метка , формат ) |
Возвращает символьное представление временной метки (аргумент 1), форматированное в соответствии с форматом (аргумент 2). |
WEEK ( дата ) |
Возвращает числовой номер недели года; неделя начинается с воскресенья |
WEEK_ISO ( дата ) |
Возвращает числовой номер недели года; неделя начинается с понедельника |
YEAR ( дата ) |
Возвращает часть значения аргумента, соответствующего году |
Скалярные функции обработки строк
Некоторые скалярные функции обработки строк приведены в таблице 4.10.
Таблица 4.10. Функции обработки строк
Функция |
Описание |
ASCII ( выражение ) |
Возвращает числовое значение ASCII кода для самого левого символа аргумента |
CHR ( выражение ) |
Возвращает символ, значение ASCII кода которого задано аргументом |
CONCAT ( выражение1 , выражение2 ) |
Возвращает строку, полученную в результате сцепления (конкатенации) двух строк, заданных аргументами |
INSERT (аргумент1, аргумент2, аргумент3, аргумент4 ) |
Возвращает строку, в которой аргумент3 байтов были удалены из строки аргумент1 (начиная с позиции аргумент2), и строка аргумент4 была вставлена в строку аргумент1 (начиная с позиции аргумент2). |
LCASE ( выражение ) LOWER ( выражение ) |
Возвращает строку, в которой все буквы преобразованы к буквам в нижнем регистре |
LEFT ( выражение1 , выражение2 ) |
Возвращает строку, представленную выражение2 лево установленными символами из строки, заданной выражением1. При необходимости, строка, заданная выражением1, дополняется справа пробелами |
LOCATE( искомая_строка , исходная_строка [ , начальная_позиция ] ) |
Возвращает начальную позицию вхождения искомой строки в исходную строку; поиск начинается с заданной начальной позиции или с начала строки, если позиция не задана |
LTRIM ( выражение ) |
Удаляет лидирующие пробелы из строки, заданной выражением |
POSSTR(исходная_строка , искомая_строка ) |
Возвращает начальную позицию вхождения искомой строки в исходную строку |
REPEAT (аргумент1 , аргумент2 ) |
Возвращает символьную строку, состоящую из аргумент1, повторенного argument2 раз |
REPLACE (аргумент1 , аргумент 2 , аргумент3) |
Замещает все вхождения аргумент2 в аргумент1 значениями аргумент3. |
RIGHT ( выражение1 , выражение2 ) |
Возвращает строку, представленную выражение2 право установленными символами из в строки, заданной выражением1. При необходимости, строка, заданная выражением1, дополняется справа пробелами |
RTRIM( выражение ) |
Удаляет хвостовые пробелы из строки, заданной выражением |
SPACE( выражение ) |
Возвращает символьную строку, состоящую из указанного выражением количества пробелов |
SUBSTR( строка , начальная_позиция [ , длина ]) |
Возвращает подстроку заданной длины из строки, начиная с начальной позиции; если длина не указана, выделяется весь остаток строки. Символы в строке нумеруются, начиная с 1 |
UCASE( выражение ) UPPER( выражение ) |
Возвращает строку, в которой все буквы преобразованы к буквам в верхнем регистре |
Некоторые дополнительные скалярные функции
Некоторые дополнительные скалярные функции приведены в таблице 4.11.
Таблица 4.11. Дополнительные функции
Функция |
Описание |
COALESCE( выражение [ , выражение … ]) |
Возвращает значение первого не NULL выражения, или NULL, если все выражения имеют NULL значение |
IDENTITY_VAL_LOCAL() |
Возвращает последнее значение, присвоенное колонке с атрибутом identity |
LENGTH( выражение ) |
Возвращает длину значения |
NULLIF( аргумент1 , аргумент2 ) |
Возвращает значение null, если аргументы равны; в противном случае возвращает значение первого аргумента |
RAISE_ERROR( sqlstate , строка_диагностики ) |
Возбуждает состояние ошибки в SQLCA. Значение sqlstate, которое должно быть возвращено, задается первым аргументом. Второй аргумент содержит произвольный текст, который должен быть возвращен |
VALUE( выражение [ , выражение … ]) |
Синоним функции COALESCE. Возвращает значение первого не NULL выражения, или NULL, если все выражения имеют NULL значение |
Предикаты
Как уже говорилось ранее, предикат определяет условие, которое может быть истинным, ложным или не определенным.
Ко всем типам предикатов применимы следующие правила:
все значения, указанные в предикате, должны быть совместимыми;
запросы, используемые в записи предикатов, часто называют подзапросами.
Некоторые предикаты были рассмотрены при описании предложения CREATE TABLE ЯОД. Ниже приводятся дополнительные способы записи предикатов, используемые при написании запросов на языке SQL.
Предикат с квантором
Предикат с квантором может быть записан двумя способами:
выражение операция_отношения квантор (запрос)
(выражение, …) = квантор_существования (запрос)
В первом случае в качестве квантора могут быть указаны квантор всеобщности ALL и кванторы существования SOME и ANY.
Во втором случае допускается использование только квантора существования SOME или ANY.
Операции отношения уже рассматривались ранее.
Предикат с квантором сравнивает значение или значения, указанные в левой части предиката (до операции отношения), с некоторым множеством значений, получаемым в результате выполнения запроса.
Запрос, записанный в предикате, должен возвращать в качестве результата любое количество строк, содержащих столько колонок, сколько выражений указано в левой части предиката (для первой формы – обязательно одна колонка, для второй – может быть несколько).
Если указывается ALL (квантор всеобщности):
результат предиката – истина, если запрос ничего не возвращает или если указанное операцией отношение истинно для каждого значения, возвращаемого запросом;
результат предиката – ложь, если указанное отношение не выполняется хотя бы для одного значения, возвращаемого запросом;
результат предиката не определен, если указанное отношение не является ложным для значений, возвращаемых запросом, и, по крайней мере, одно сравнение не определено из-за NULL значений.
Если указываются SOME или ANY (кванторы существования):
результат предиката – истина, если указанное отношение истинно для каждого значения хотя бы одной строки, возвращаемой запросом;
результат предиката – ложь, если запрос ничего не возвращает или если указанное отношение не выполняется хотя бы для одного значения в каждой строке, возвращаемой запросом;
результат предиката не определен, если указанное отношение не является истинным для строк, возвращаемых запросом, и, по крайней мере, одно сравнение не определено из-за NULL значений.
Примеры
Рассмотрим следующие таблицы:
TBLAB |
COLA |
COLB |
|
TBLXY |
COLX |
COLY |
|
1 |
12 |
|
|
2 |
22 |
|
2 |
12 |
|
|
3 |
23 |
|
3 |
13 |
|
|
|
|
|
4 |
14 |
|
|
|
|
|
- |
- |
|
|
|
|
Пример 1.
Рассмотрим предикат COLA = ANY(SELECT COLX FROM TBLXY)
Запрос, записанный в предикате, возвращает в качестве результата значения 2 и 3.
Предикат возвращает следующие результаты:
«истина» для второй и третьей строк таблицы TABLAB, в которых значение колонки COLA совпадает, по крайней мере, с одним значением из запроса;
«ложь» для первой и четвертой строк таблицы, в которых значение колонки COLA не совпадает ни с одним значением из запроса;
«не определено» для последней строки таблицы TABLAB, поскольку в ней присутствует NULL значение (-) колонки COLA.
Пример 2.
Рассмотрим предикат COLA > ALL(SELET COLX FROM TBLXY)
Запрос, использованный в предикате, возвращает в качестве результата значения 2 и 3.
Предикат возвращает следующие результаты:
«истина» для четвертой строки таблицы TABLAB, в которой значение колонки COLA превышает все значения из запроса;
«ложь» для первой, второй и третьей строк таблицы, в которых значения колонки COLA меньше или равно, по крайней мере, одному значению из запроса;
«не определено» для последней строки таблицы TABLAB, поскольку в ней присутствует NULL значение (-) колонки COLA.
Пример 3.
Рассмотрим предикат COLA > ALL(SELECT COLX FROM TBLXY WHERE COLX < 0)
Запрос, использованный в предикате, ничего не возвращает, поэтому предикат вернет в качестве результата значение «истина» для всех строк таблицы TABLAB.
Предикат EXISTS
Предикат EXISTS имеет следующий вид:
EXISTS (запрос)
Предикат проверяет, формирует ли запрос не пустой результат.
Запрос может вернуть любое количество любых строк, и
результат предиката – истина, если запрос вернет, по крайней мере, одну строку;
результат предиката – ложь, если запрос не возвращает ни одной строки;
результат предиката не может быть не определен.
Предикат IN
Помимо рассмотренных ранее форм предиката IN, существуют еще две:
выражение1 [NOT] IN (запрос1)
(выражение2, …) [NOT] IN (запрос2)
Запрос, записанный в предикате, должен возвращать столько колонок в результате, сколько выражений указано слева от ключевого слова IN. Так, запрос1 должен возвращать одну колонку, а запрос2 – несколько.
Выражение1 и колонка в запросе1 должны быть сопоставимыми. Каждое выражение2 и соответствующая ему колонка в запросе2 должны быть сопоставимыми.
Предикат IN эквивалентен предикатам с кванторами. Эквивалентность предикатов представлена в таблице 4.12.
Таблица 4.12. Эквивалентность предикатов
Предикат IN |
Эквивалентный предикат с квантором |
выражение IN (запрос) |
выражение = ANY(запрос) |
выражение NOT IN (запрос) |
выражение <> ALL(запрос) |
(выражение1, выражение2, …) IN (запрос) |
(выражение1, выражение2, …) = ANY(запрос) |
Предикат NULL
Предикат NULL имеет следующий вид:
выражение IS [NOT] NULL
Предикат проверяет наличие неопределенного значения.
Следует отметить, что предикат IS NULL не может быть заменен основным предикатом выражение = NULL. Если в операции сравнения хотя бы один операнд имеет значение NULL, результат операции – не определен, независимо от значения второго операнда. Поэтому приведенный здесь основной предикат вернет результат «не определено» независимо от результата вычисления выражения, тогда как предикат IS NULL возвращает результат – «истина» или «ложь».
Результат предиката NULL не может быть неопределенным. Если значение выражения – NULL, результат – истина; если значение – не NULL, результат – ложь.
Предложения языка манипулирования данными
Предложение INSERT
Предложение INSERT позволяет вставлять в таблицу новые строки.
В общем случае предложение INSERT имеет следующий вид:
INSERT INTO имя_таблицы [(имя_колонки, …)] VALUES (значение, …), (…), …
имя_таблицы – должно указывать существующую таблицу базы данных, в которую вставляются новые значения (строки).
(имя_колонки, …) – указывает имена колонок, для которых в данном предложении представляются значения. Каждое имя называет имя колонки в данной таблице; одно и то же имя колонки не должно указываться дважды. Если список имен колонок опущен, предполагается, что перечислены все имена колонок данной таблицы в том порядке, в каком эти колонки располагаются в таблице (порядок расположения колонок в таблице определяется порядком их перечисления в предложении CREATE TABLE). Если в списке имен колонок указаны не все колонки таблицы, для тех колонок, которые не указаны, при создании таблицы должны быть определены либо атрибут NULL, либо атрибут генерируемого значения (WITH DEFAULT или GENERATED …).
(значение, …), (…), … – определяет вставляемые значения, т.е. значения одной или нескольких новых строк, вставляемых в таблицу. Значения, соответствующие одной строке таблицы, указываются внутри парных круглых скобок. Если необходимо вставить несколько строк, группа значений для каждой строки заключается в парные круглые скобки, и группы перечисляются через запятую.
Количество значений, указанных в каждой строке, должно соответствовать явному или неявному списку имен колонок. Первое значение вставляется в первую колонку списка, второе – во вторую, и т.д. Тип вставляемых значений должен соответствовать типу соответствующих им колонок.
Каждое значение, указанное в списке, должно быть представлено некоторым выражением или ключевыми словами NULL или DEFAULT.
В качестве выражения может быть использована любая конструкция, описанная в разделе «Выражения».
NULL – определяет пустое значение; слово может быть указано только для колонки, для которой разрешены неопределенные значения.
DEFAULT – указывает, что должно быть использовано значение по умолчанию. Результат зависит от того, как была определена колонка при создании таблицы:
если колонка была определена как генерируемая на основе выражения, значение колонки генерируется системой на основе заданного выражения;
если для колонки была использована спецификация IDENTITY, значение генерируется менеджером базы данных;
если для колонки была использована спецификация WITH DEFAULT, вставляется то значение, которое было определено для колонки в предложении CREATE TABLE.
Если в таблице какая-либо колонка определена с атрибутом GENERATED ALWAYS, при вставке данных в такую таблицу либо явно задается список имен колонок, не содержащий указанную колонку, либо для этой колонки в качестве значения по умолчанию должно быть указано слово DEFAULT. Если GENERATED ALWAYS колонка указана в списке колонок предложения INSERT со значением не DEFAULT в конструкции VALUES, возникает ошибка.
Например, пусть таблица TABID была создана следующим образом:
CREATE TABLE TABID (
ID_T INT NOT NULL GENERATED ALWAYS AS IDENTITY
)
Если в данную таблицу необходимо вставить новую строку, предложение INSERT должно быть записано следующим образом:
INSERT INTO TABID
VALUES (DEFAULT)
Если в таблицу нужно вставить несколько строк, предложение INSERT будет иметь следующий вид:
INSERT INTO TABID
VALUES (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT)
Когда генерируется очередное значение для колонки с атрибутом identity, такое сгенерированное значение считается использованным; в следующий раз, когда потребуется значение, будет сгенерировано новое значение. Это выполняется даже в тех случаях, когда предложение INSERT, включающее колонку identity, завершается с ошибкой или откатывается.
Существует и вторая форма предложения INSERT, в соответствии с которой новые строки, вставляемые в таблицу, получаются в результате выполнения некоторого запроса к базе данных. Эта форма имеет следующий вид:
INSERT INTO имя_таблицы [(имя_колонки, …)] запрос
В этом случае совокупность новых строк, которые должны быть вставлены, определяется в виде результата выполнения запроса. Может быть вставлена одна строка, много строк или ни одной строки. Количество колонок в результате выполнения запроса должно совпадать с количеством колонок, указанным (явно или неявно) в списке. Значение первой колонки результата вставляется в первую колонку списка, второй колонки результата – во вторую колонку списка, и т.д.
Если в запросе используется та же таблица, в которую вставляются новые строки, запрос выполняется перед вставкой в таблицу хотя бы одной новой строки.
Если при создании таблицы для нее были определены какие-либо ограничения целостности, при вставке в таблицу новых строк для каждой строки проверяются все ограничения. Если хотя бы одно ограничение будет нарушено, новые строки в таблицу не вставляются, и операция завершается с ошибкой.
Примеры
Пусть таблица DEPARTMENT имеет следующую структуру:
Имя колонки |
DeptNo |
DeptName |
MgrNo |
AdmrDept |
Тип данных |
CHAR(3) NOT NULL |
VARCHAR(29) NOT NULL |
CHAR(6) |
CHAR(3) NOT NULL |
Описание |
Номер отдела |
Название, определяющее направление деятельности отдела |
Номер сотрудника – руководителя отдела |
Номер отдела, которому подчиняется данный отдел |
Пример 1. Вставить в таблицу DEPARTMENT следующую информацию о новом отделе: номер отдела – ‘E31’, название – ‘ARCHITECTURE’, номер руководителя отдела – ‘00390’, вышестоящий отдел – ‘E01’.
INSERT INTO DEPARTMENT
VALUES (’E31’, ’ARCHITECTURE’, ’00390’, ’E01’)
Пример 2. Вставить в таблицу DEPARTMENT ту же информацию, что и в примере 1, за исключением номера руководителя отдела.
INSERT INTO DEPARTMENT (DeptNo, DeptName, AdmrDept)
VALUES (’E31’, ’ARCHITECTURE’, ’E01’)
или, что то же самое,
INSERT INTO DEPARTMENT
VALUES (’E31’, ’ARCHITECTURE’, NULL, ’E01’)
Пример 3. Вставить в таблицу DEPARTMENT в одном предложении INSERT информацию о двух отделах, для которых не назначены руководители.
INSERT INTO DEPARTMENT (DeptNo, DeptName, AdmrDept)
VALUES (’B11’, ’PURCHASING’, ’B01’),
(’E41’, ’DATABASE ADMINISTRATION’, ’E01’)
Пример 4.
Таблица EMP_ACT имеет следующую структуру:
Имя колонки |
EmpNo |
ProjNo |
ActNo |
EmpTime |
EmStDate |
EmEnDate |
Тип данных |
CHAR(6) NOT NULL |
CHAR(6) NOT NULL |
SMALLINT NOT NULL |
DEC(5,2) |
DATE |
DATE |
Описание |
Номер сотрудника |
Номер проекта |
Номер задания |
Доля времени, затрачиваемая сотрудником на выполнение задания |
Дата начала работы над заданием |
Дата завершения задания |
Необходимо создать временную таблицу MA_EMP_ACT, имеющую такую же структуру, и загрузить в нее те строки из таблицы EMP_ACT, для которых номер проекта (ProjNo) начинается буквами ‘MA’.
CREATE TABLE MA_EMP_ACT (
EmpNo CHAR(6) NOT NULL,
ProjNo CHAR(6) NOT NULL,
ActNo SMALLINT NOT NULL,
EmpTime DEC(5,2),
EmStDate DATE,
EmEnDate DATE )
INSERT INTO MA_EMP_ACT
SELECT * FROM EMP_ACT
WHERE ProjNo LIKE ’MA%’
Предложение DELETE
Предложение DELETE позволяет удалять из таблицы все или некоторые строки.
В общем случае предложение DELETE имеет следующий синтаксис:
DELETE FROM имя_таблицы [WHERE условие_поиска]
имя_таблицы – должно указывать существующую таблицу базы данных.
условие_поиска – определяет условие отбора удаляемых строк. Если конструкция WHERE опущена, удаляются все строки таблицы.
В условии поиска в конструкции WHERE могут быть использованы только колонки таблицы, указанной в предложении DELETE. Условие поиска применяется к каждой строке таблицы, и удаляются те строки, для которых результатом условия поиска является значение true. Если условие поиска содержит подзапрос, можно считать, что подзапрос будет выполняться каждый раз, когда условие поиска применяется к строке, и результаты подзапроса используются в условии поиска. Если подзапрос ссылается на таблицу, указанную в этом же предложении DELETE, или на зависимые таблицы по правилу удаления CASCADE или SET NULL, подзапрос выполняется полностью, прежде чем будет удалена хотя бы одна строка.
При удалении строк из родительской таблицы проверяются ограничения ссылочной целостности и правила удаления, определенные в дочерних таблицах. Если для какой-либо из дочерних таблиц определено правило удаления RESTRICT, строки из родительской таблицы не удаляются, и предложение DELETE завершается с ошибкой. Если операция удаления не защищена правилом удаления RESTRICT, выбранные строки удаляются. Кроме того, оказывается воздействие на строки дочерних таблиц, зависящие от удаляемых строк:
– колонкам внешнего ключа любых строк, зависящих по связям с правилом удаления SET NULL, присваивается значение NULL;
– любые строки, зависящие по связям с правилом удаления CASCADE, также удаляются, и правила удаления применяются, в свою очередь, и к этим строкам.
Правило удаления NO ACTION проверяется, чтобы гарантировать, что любой not-null внешний ключ ссылается на существующую родительскую строку после того, как будут удовлетворены другие ссылочные ограничения.
Если при выполнении предложения DELETE, удаляющего несколько строк, возникла ошибка, никакие изменения в базе данных не происходят.
Примеры
Пример 1. Удалить из таблицы DEPARTMENT отдел с номером (DeptNo) ‘D11’
DELETE FROM DEPARTMENT
WHERE DeptNo = ’D11’
Пример 2. Удалить из таблицы DEPARTMENT все строки (т.е. опустошить таблицу).
DELETE FROM DEPARTMENT
Пример 3. Удалить из таблицы EMPLOYEE сотрудников, выполняющих операции SALESREP или FIELDREP, кто не выполнял продажи в 1995 г.
DELETE FROM EMPLOYEE
WHERE Job IN (’SALESREP’,’FIELDREP’)
AND
LastName NOT IN (SELECT Sales_Person
FROM SALES
WHERE YEAR(Sales_Date)=1995)
Предложение UPDATE
Предложение UPDATE позволяет изменить значения указанных колонок во всех или некоторых строках таблицы.
В общем случае предложение UPDATE имеет следующий вид:
UPDATE имя_таблицы SET имя_колонки = значение, … [WHERE условие_поиска]
имя_таблицы – должно указывать имя существующей таблицы базы данных.
Конструкция SET определяет, какие колонки таблицы и каким образом изменяют свои значения.
имя_колонки – указывает колонку, значение которой должно быть модифицировано. Имя одной и той же колонки в конструкции SET не должно повторяться.
значение – указывает новое значение колонки. Может быть представлено некоторым выражением или ключевыми словами NULL или DEFAULT и подчиняется тем же правилам, в соответствии с которыми задается новое значение в предложении INSERT. Кроме того, в выражении может быть использовано имя обновляемой колонки.
условие_поиска – условие, определяющее, какие строки должны быть модифицированы. Если конструкция WHERE опущена, модифицируются все строки таблицы.
В условии поиска в конструкции WHERE могут быть использованы только колонки таблицы, указанной в предложении UPDATE. Условие поиска применяется к каждой строке таблицы, и модифицируются те строки, для которых результатом условия поиска является значение true. Если условие поиска содержит подзапрос, можно считать, что подзапрос будет выполняться каждый раз, когда условие поиска применяется к строке, и результаты подзапроса используются в условии поиска. Если подзапрос ссылается на таблицу, указанную в этом же предложении UPDATE, подзапрос выполняется полностью прежде, чем будет обновлена хотя бы одна строка таблицы.
Если в предложении UPDATE модифицируются колонки таблицы, для которых определены некоторые ограничения целостности, все ограничения проверяются, и если хотя бы одно из них будет нарушено, соответствующая таблица изменена не будет, а предложение UPDATE завершится с ошибкой.
Примеры
Пример 1. Изменить должность (JOB) сотрудника с номером (EMPNO) ‘000290’ в таблице EMPLOYEE на ‘LABORER’.
UPDATE EMPLOYEE
SET JOB = ’LABORER’
WHERE EMPNO = ’000290’
Пример 2. Увеличить значение колонки PRSTAFF (оценка средней обеспеченности проекта персоналом) в таблице PROJECT на 1.5 для всех проектов, за которые отвечает отдел (DEPTNO) с кодом ‘D21’.
UPDATE PROJECT
SET PRSTAFF = PRSTAFF + 1.5
WHERE DEPTNO = ’D21’
Пример 3. Для всех сотрудников, кроме менеджера отдела (WORKDEPT) ‘E21’, были сделаны временные переназначения. Необходимо отразить эту операцию, установив в таблице EMPLOYEE должность (JOB) соответствующих сотрудников в NULL и их оплату (SALARY, BONUS, COMM) в 0.
UPDATE EMPLOYEE
SET JOB=NULL, SALARY=0, BONUS=0, COMM=0
WHERE WORKDEPT = ’E21’ AND JOB <> ’MANAGER’
Это предложение может быть также записано следующим образом:
UPDATE EMPLOYEE
SET (JOB, SALARY, BONUS, COMM) = (NULL, 0, 0, 0)
WHERE WORKDEPT = ’E21’ AND JOB <> ’MANAGER’
Конструкция VALUES
Конструкция VALUES представляет собой форму запроса, возвращающую некоторую таблицу.
В конструкции VALUES указываются одна или несколько строк, перечисляемых через запятую:
VALUES строка, …
Конструкция VALUES позволяет определить некоторую таблицу, явно задавая значения колонок и строк этой таблицы. Каждая строка конструкции VALUES задает одну строку таблицы и может быть представлена в виде одного выражения, определяющего таблицу, содержащую только одну колонку, или в виде списка выражений, перечисленных через запятую и заключенных в круглые скобки: (выражение, …), задающих многоколоночную таблицу. Если в конструкции VALUES указывается несколько строк, все строки должны иметь одинаковое количество колонок, и соответствующие значения каждой строки должны быть совместимыми.
Вместо выражения в многострочной конструкции VALUES может быть указано значение NULL, только если, по крайней мере, в одной строке в той же самой колонке указано не NULL значение.
Рассмотрим некоторые примеры.
VALUES (1), (2), (3) – определяет таблицу, содержащую 3 строки, состоящие из одной колонки.
VALUES 1, 2, 3 – эквивалентно предыдущему примеру: 3 строки из одной колонки.
VALUES (1, 2, 3) – определяет таблицу, содержащую одну строку из трех колонок.
VALUES (1, 21), (2, 22), (3, 23) – определяет таблицу, содержащую три строки из двух колонок.
Предложение SELECT
В общем случае, предложение SELECT состоит из семи конструкций и имеет следующий вид:
SELECT список_вывода
FROM источники
WHERE условие_отбора_строк
GROUP BY список_для_группирования
HAVING условие_отбора_групп
ORDER BY список_для_упорядочивания
FETCH FIRST ограничение_вывода
Предложение SELECT реализует запросы к базе данных, и поэтому его часто называют запросом. Внутри одного предложения SELECT могут использоваться другие предложения; такие вложенные предложения SELECT часто называют подзапросом. В дальнейшем мы будем использовать эти два термина.
В результате выполнения запроса, представленного предложением SELECT, формируется результирующая таблица, вид и состав которой определяются следующим образом:
конструкция SELECT определяет совокупность колонок результирующей таблицы и их имена;
конструкция FROM определяет, из каких таблиц объектов базы данных извлекаются данные в результирующую таблицу;
конструкция WHERE определяет дополнительные условия, накладываемые на строки данных, которые должны войти в результирующую таблицу;
конструкция GROUP BY позволяет сгруппировать строки по определенному признаку для последующей обработки; определяет некоторую совокупность групп, каждая из которых состоит из нескольких строк данных;
конструкция HAVING позволяет из всех групп выбрать некоторые группы, удовлетворяющие дополнительным условиям;
конструкция ORDER BY позволяет упорядочить строки результирующей таблицы;
конструкция FETCH FIRST позволяет ограничить результирующую таблицу заданным количеством строк.
Все конструкции, кроме SELECT и FROM, являются не обязательными и могут быть опущены; если же все они или некоторые из них указываются, они должны быть записаны именно в таком порядке, в каком представлены в описании предложения SELECT.
Не вдаваясь в особенности работы СУБД, можно считать, что конструкции запроса обрабатываются последовательно, в некотором порядке; на каждом этапе формируется некоторая промежуточная результирующая таблица, которая используется в качестве исходной таблицы на следующем этапе. Порядок обработки запроса следующий:
FROM – выделяются таблицы и представления, из которых выбираются нужные данные.
WHERE – из выбранных таблиц выбираются строки, удовлетворяющие указанному условию отбора строк.
GROUP BY – выбранные строки объединяются в группы (группируются) по указанным признакам.
HAVING – из созданных групп выделяются группы, удовлетворяющие условию отбора групп.
SELECT – из выбранных групп в соответствии со списком вывода выделяются и обрабатываются необходимые данные, создавая строки и столбцы результирующей таблицы.
ORDER BY – полученные строки упорядочиваются по указанным столбцам.
FETCH FIRST – из полученных строк выбираются первые указанное количество строк.
Рассмотрим особенности задания каждой конструкции предложения SELECT.
Конструкция SELECT
Конструкция SELECT имеет следующий вид:
SELECT список_вывода
список вывода определяет колонки в результирующей таблице и представляет собой совокупность элементов, перечисленных через запятую, которым может предшествовать ключевое слово DISTINCT или ALL. Слово DISTINCT предписывает, в случае если в результирующей таблице встречаются повторяющиеся строки, выводить только одну (любую) строку из группы повторяющихся строк, тогда как слово ALL предписывает выводить все строки. Если ни одно из этих слов не указано, по умолчанию предполагается, что задано ALL.
Чаще всего в качестве элемента списка вывода используется имя колонки таблицы, указанной в конструкции FROM. Каждое имя колонки должно однозначно идентифицировать колонку таблицы. Если в запросе используются несколько таблиц, имеющих одинаковые имена колонок, и в списке вывода необходимо указать имя такой колонки, оно должно быть уточнено именем таблицы: имя_таблицы.имя_колонки – получается так называемое уточненное имя.
Если требуется получить все колонки таблицы, вместо перечисления имен колонок можно указать символ *. Если в запросе используются несколько таблиц, и из некоторой таблицы (или из всех таблиц) нужно получить все колонки, используется конструкция имя_таблицы.*.
В качестве элемента списка вывода может быть указана константа или выражение, которое строится в соответствии с правилами записи выражений, рассмотренными выше. В этих случаях соответствующая колонка результирующей таблицы оказывается безымянной. Чтобы определить имя колонки результирующей таблицы, или переименовать колонку результата, используется следующая конструкция:
элемент AS новое_имя
Новое имя задается в виде идентификатора – простого или с ограничителем.
Кроме того, в качестве элемента списка вывода может быть указан скалярный подзапрос – запрос, который возвращает только одну строку, возможно, содержащую несколько колонок. В этом случае элемент списка вывода задается следующим образом:
(запрос) AS имя_строки (имя_колонки, …)
Список имен колонок опускается, если запрос возвращает единственное значение.
Имена результирующих колонок формируются в соответствии со следующими правилами:
если указана конструкция AS, именем результирующей колонки является имя, указанное в конструкции AS;
если конструкция AS не указанна и результирующая колонка получается из колонки таблицы, тогда именем результирующей колонки является не уточненное имя колонки таблицы;
в остальных случаях результирующая колонка будет безымянной. Таким колонкам система назначает временные номера (в виде символьных строк).
Рассмотрим некоторые примеры задания конструкции SELECT.
Предположим, что есть две таблицы – T1 и T2. Пусть в таблице T1 определены колонки T1_ID, TName, TNum, а в таблице T2 – колонки T2_ID, T1_ID и TName.
Тогда предложению SELECT * FROM T1 соответствует следующий заголовок результирующей таблицы:
T1_ID |
TNAME |
TNum |
Предложению SELECT DISTINCT TNAME, TNUM FROM T1 соответствует следующий заголовок результирующей таблицы:
TNAME |
TNUM |
Данное предложение SELECT реализует операцию проекции реляционной алгебры.
Предложению SELECT DISTINCT T1.TNAME, T2.TNAME FROM T1, T2 соответствует следующий заголовок результирующей таблицы:
TNAME |
TNAME |
Предложению SELECT T1_ID, TNAME AS "Name for Table" FROM T1 соответствует следующий заголовок результирующей таблицы:
T1_ID |
Name for Table |
Предложению SELECT T1_ID, TName, TNum + 100 FROM T1 соответствует следующий заголовок результирующей таблицы:
T1_ID |
TName |
3 |
Предложению SELECT T1.*, T2.* FROM T1, T2 соответствует следующий заголовок результирующей таблицы:
T1_ID |
TName |
TNum |
T2_ID |
T1_ID |
TName |
Следующий пример предложения SELECT содержит ошибку:
SELECT T1_ID, T2_ID FROM T1, T2
Имя колонки T1_ID встречается и в T1, и в T2, поэтому имя T1_ID в списке вывода в заголовке
SELECT не однозначно.
Конструкция FROM
Конструкция FROM, в общем случае, может быть представлена следующим образом:
FROM элемент1, элемент2, …
Каждый элемент может быть представлен в виде ссылки на таблицу, соединения таблиц или вложенного табличного выражения.
Ссылка на таблицу имеет следующий вид:
имя_таблицы [[AS] корреляционное имя ]
Имя таблицы должно определять существующую таблицу базы данных.
Корреляционное имя, если оно используется, заменяет (в пределах данного предложения SELECT) непосредственно предшествующее ему имя таблицы. Если для таблицы указано корреляционное имя, именно оно должно использоваться при записи уточненного имени колонки такой таблицы. Если одна и та же таблица указывается в конструкции FROM дважды, по крайней мере, после одного указания должно следовать корреляционное имя.
Предложение SELECT T1.*, T2.* FROM T1, T2 реализует операцию декартова произведения.
Соединение таблиц записывается следующим образом:
элемент1 [тип_соединения] JOIN элемент2 ON условие_соединения
Здесь каждый элемент также может быть представлен в виде ссылки на таблицу, соединения таблиц или вложенного табличного выражения.
В качестве типа соединения может быть указано внутреннее (INNER) или внешнее (OUTER) соединение. Если тип соединения не указан, по умолчанию принимается внутреннее соединение.
Для внешнего соединения должен быть обязательно указан его вид: левое (LEFT), правое (RIGHT) или полное (FULL) внешнее соединение. При этом ключевое слово OUTER может быть опущено; так, указание LEFT JOIN эквивалентно LEFT OUTER JOIN.
Условие соединения записывается аналогично условию поиска, за следующими ограничениями:
любая колонка, на которую ссылается выражение в условии соединения, должна быть колонкой одной из таблиц, указанных в соответствующей операции соединения;
условие соединения не может содержать никаких подзапросов.
Соединение таблиц реализует соответствующую операцию соединения реляционной алгебры.
Рассмотрим примеры.
Пусть даны две таблицы – T1 и T2, имеющие следующее содержание:
T1 |
W |
X |
|
T2 |
Y |
Z |
|
A |
11 |
|
|
A |
21 |
|
B |
12 |
|
|
C |
22 |
|
C |
13 |
|
|
D |
23 |
Ниже приведены результаты всех операций соединения.
Внутреннее соединение – T1 INNER JOIN T2 ON W = Y
W |
X |
Y |
Z |
A |
11 |
A |
21 |
C |
13 |
C |
22 |
Левое внешнее соединение – T1 LEFT OUTER JOIN T2 ON W=Y
W |
X |
Y |
Z |
A |
11 |
A |
21 |
B |
12 |
- |
- |
C |
13 |
C |
22 |
Правое внешнее соединение – T1 RIGHT OUTER JOIN T2 ON W=Y
W |
X |
Y |
Z |
A |
11 |
A |
21 |
C |
13 |
C |
22 |
- |
- |
D |
23 |
Полное внешнее соединение – T1 FULL OUTER JOIN T2 ON W=Y
W |
X |
Y |
Z |
A |
11 |
A |
21 |
C |
13 |
C |
22 |
- |
- |
D |
23 |
B |
12 |
- |
- |
В соответствии с определением элементов, используемых в соединении таблиц, соединение может быть вложено в другое соединение. Несколько соединений обычно выполняются в порядке слева направо, основываясь на положении требуемого условия соединения. Для улучшения читабельности при использовании вложенных соединений рекомендуется использовать скобки. Например, конструкция:
TB1 LEFT JOIN TB2 ON TB1.C1=TB2.C1
RIGHT JOIN TB3 LEFT JOIN TB4 ON TB3.C1=TB4.C1
ON TB1.C1=TB3.C1
Эквивалентна следующей:
(TB1 LEFT JOIN TB2 ON TB1.C1=TB2.C1)
RIGHT JOIN (TB3 LEFT JOIN TB4 ON TB3.C1=TB4.C1)
ON TB1.C1=TB3.C1
Подзапрос, представленный предложением SELECT и заключенный в скобки, за которым следует корреляционное имя, называется вложенным табличным выражением. Подзапросу может предшествовать ключевое слово TABLE, и за подзапросом обязательно должно быть указано корреляционное имя:
[TABLE] (подзапрос) [AS] корреляционное_имя [(имя_колонки, …)]
В результате выполнения подзапроса, включенного во вложенное табличное выражение, получается некоторая результирующая таблица. Корреляционное имя, указанное после подзапроса, определяет имя этой результирующей таблицы; имена колонок определяются конструкцией SELECT подзапроса. Вместе с корреляционным именем могут быть указаны имена_колонок, определяющие имена колонок результирующей таблицы. На колонки вложенного табличного выражения можно ссылаться из любых мест запроса с помощью корреляционного имени. В общем случае, вложенное табличное выражение может быть указано в любой конструкции FROM.
Пример записи вложенного табличного выражения:
SELECT T1.A, T2.B FROM T1, (SELECT … FROM TT) AS T2(B …) …
Во вложенном табличном выражении могут быть использованы уточненные имена, ссылающиеся на таблицу, использованную в основном запросе; в этом случае вложенному табличному выражению должно обязательно предшествовать ключевое слово TABLE.
Рассмотрим пример. В запросе используются таблица Dept, имеющая колонки DeptNo и DeptName, и вложенное табличное выражение, в котором используется таблица Emp, имеющая числовую колонку Sal и колонку DeptNo; в табличном выражении необходимо реализовать ссылку на колонку DeptNo из таблицы Dept. Ниже приведен корректный пример такого запроса:
SELECT D.DeptNo, D.DeptName, E1.avgsal, E1.empcount
FROM Dept D,
TABLE (SELECT AVG(E.Sal) AS avgsal,
COUNT(*) AS empcount
FROM Emp E
WHERE E.DeptNo=D.DeptNo
) AS E1;
Если ключевое слово TABLE в таком запросе будет опущено, во вложенном табличном выражении ссылка D.DeptNo будет не определена.
Конструкция WHERE
Конструкция WHERE задает условие отбора строк и имеет следующий вид:
WHERE условие_поиска
В результате обработки данной конструкции будут получены строки, для которых указанное условие_поиска истинно.
Условие поиска записывается в соответствии с правилами, рассмотренными выше, с учетом следующих ограничений:
в условии поиска каждое используемое имя колонки или уточненное имя должно уникально идентифицировать колонку исходной таблицы или вложенного табличного выражения, указанных в конструкции FROM;
в условии поиска конструкции WHERE не могут быть использованы агрегатные функции.
Конструкция GROUP BY
Конструкция GROUP BY имеет следующий вид:
GROUP BY элемент [, элемент …]
Конструкция GROUP BY включается в предложение SELECT в тех случаях, когда в список вывода конструкции SELECT включаются, в том числе, и выражения, содержащие агрегатные функции.
Элемент конструкции GROUP BY представляется в виде некоторого выражения группирования, содержащего имена колонок и используемого для определения группы строк. Каждое имя колонки, включенное в выражение группирования, должно однозначно идентифицировать колонку исходной таблицы.
Каждому выражению списка вывода, не содержащему агрегатную функцию, должно соответствовать выражение группирования. В простейшем случае выражение группирования представляется именем одной колонки. Выражение группирования не может включать скалярный запрос. Чтобы выполнять группирование с использованием таких выражений, используются вложенные табличные выражения.
Результатом выполнения операции GROUP BY является множество групп строк. Каждая группа состоит из множества строк, имеющих одно и то же значение выражения группирования. При выполнении группирования все значения NULL из выражения группирования считаются равными.
Конструкция HAVING
Конструкция HAVING имеет следующий вид:
HAVING условие_поиска
Конструкция HAVING определяет промежуточную таблицу результатов, которая состоит из групп, полученных на предыдущих этапах вычисления SELECT, для которых условие поиска истинно.
В условии поиска конструкции HAVING допускается использование имен колонок, однозначно идентифицирующих каждую группу исходной таблицы, и агрегатных функций, применяемых к полученным группам.
Допускается использование конструкции HAVING без конструкции GROUP BY; в этом случае считается, что в операции HAVING участвует только одна группа, и в списке вывода в конструкции SELECT могут быть указаны только агрегатные функции, константы и/или специальные регистры.
Конструкция ORDER BY
Конструкция ORDER BY имеет следующий синтаксис:
ORDER BY ключ_сортировки [направление_сортировки] , …
В качестве ключа_сортировки могут быть указаны простое имя колонки или простое целое. Простое имя колонки определяет именованную колонку из списка вывода конструкции SELECT. Простое целое задает порядковый номер колонки результирующей таблицы, начиная с 1.
В качестве направления сортировки может быть указано ключевое слово ASC или DESC. Значение ASC предписывает выполнять сортировку в возрастающем порядке, DESC – в убывающем порядке. Если направление сортировки не указано, по умолчанию принимается ASC.
Конструкция ORDER BY определяет упорядочение строк результирующей таблицы. Если указана только одна спецификация сортировки (ключ сортировки с соответствующим направлением), строки упорядочиваются по значениям указанной спецификации. Если указано несколько спецификаций сортировки, строки упорядочиваются сначала по значениям первой спецификации, затем по значениям второй, и т.д.
Упорядочение выполняется в соответствии с правилами сравнения. Значение NULL считается большим, чем любое другое значение. Если конструкция ORDER BY не может полностью упорядочить строки, строки с одинаковыми значениями всех указанных в ключах сортировки колонок выводятся в произвольном порядке.
Конструкция FETCH FIRST
Конструкция FETCH FIRST имеет следующий вид:
FETCH FIRST [целое] ROW[S] ONLY
Конструкция FETCH FIRST устанавливает максимальное количество строк, которые должны быть получены. Она сообщает менеджеру базы данных, что приложение не хочет получить более чем целое строк, независимо от того, сколько строк может быть получено в результирующей таблице, если эта конструкция не указывается. Попытка получить больше, чем целое, строк обрабатывается так же, как и обычный конец данных. Значение целого должно быть строго положительным (нуль не допускается).
Использование теоретико-множественных операций
При написании запросов к базе данных, наряду с рассмотренными выше возможностями, могут быть использованы теоретико-множественные операции объединения, вычитания и пересечения. Запросы, использующие теоретико-множественные операции, будем в дальнейшем называть запросами, а запросы без теоретико-множественных операций – подзапросами.
Запрос является компонентом некоторых предикатов, которые, в свою очередь, являются компонентами других предложений SQL. Запрос, являющийся компонентом предиката, также называют подзапросом.
Запрос имеет следующий вид:
операнд [операция операнд …] [конструкция ORDER BY] [конструкция FETCH FIRST]
В качестве операнда может быть использован подзапрос, запрос, заключенный в круглые скобки – (запрос), и конструкция VALUES.
В качестве операций используются:
UNION или UNION ALL – для операции объединения,
EXCEPT или EXCEPT ALL – для операции вычитания,
INTERSECT или INTERSECT ALL – для операции пересечения.
Указанные операции реализуют соответствующие теоретико-множественные операции реляционной алгебры. Ключевое слово ALL для каждой операции указывает, что в результат должны быть включены все строки, независимо от того, встречаются дубликаты среди строк или нет. Если ключевое слово ALL не указано, из результатов, в соответствии с определением теоретико-множественных операций, удаляются все дубликаты. Две строки считаются дубликатами, если каждое значение первой строки равно соответствующему значению второй. При анализе дубликатов два значения NULL считаются равными.
Количество колонок в таблицах R1 и R2, соответствующих каждому операнду в записи запроса, должно быть одинаковым. Имена колонок в результирующей таблице определяются следующим образом:
если n-я колонка R1 и n-я колонка R2 имеют одно и то же имя, тогда n-я колонка результата получает это же имя;
если n-я колонка R1 и n-я колонка R2 имеют разные имена, имя результирующей таблицы генерируется системой; такое имя не может быть использовано в конструкции ORDER BY.
Конструкции ORDER BY и FETCH FIRST имеют такой же смысл, что и соответствующие конструкции, рассмотренные выше.
Если в записи полного запроса используется несколько теоретико-множественных операций, они выполняются в порядке слева направо, причем операция INTERSECT имеет более высокий приоритет, чем операции UNION и EXCEPTION (эти операции имеют одинаковый приоритет). Скобки могут изменить порядок вычисления операций.
В таблице 4.13 приведены результаты вычисления выражений R1 операция R2 для всех теоретико-множественных операций.
Таблица 4.13. Результаты вычисления теоретико-множественных операций
R1 |
R2 |
UNION ALL |
UNION |
EXCEPT ALL |
EXCEPT |
INTERSECT ALL |
INTERSECT |
1 |
1 |
1 |
1 |
1 |
2 |
1 |
1 |
1 |
1 |
1 |
2 |
2 |
5 |
1 |
3 |
1 |
3 |
1 |
3 |
2 |
|
3 |
4 |
2 |
3 |
1 |
4 |
2 |
|
4 |
|
2 |
3 |
1 |
5 |
4 |
|
|
|
2 |
3 |
2 |
|
5 |
|
|
|
3 |
4 |
2 |
|
|
|
|
|
4 |
|
2 |
|
|
|
|
|
4 |
|
3 |
|
|
|
|
|
5 |
|
3 |
|
|
|
|
|
|
|
3 |
|
|
|
|
|
|
|
3 |
|
|
|
|
|
|
|
3 |
|
|
|
|
|
|
|
4 |
|
|
|
|
|
|
|
4 |
|
|
|
|
|
|
|
4 |
|
|
|
|
|
|
|
5 |
|
|
|
|
|
Создание представлений – CREATE VIEW
Предложение CREATE VIEW создает представления на основе одной или нескольких таблиц и/или других представлений.
Предложение CREATE VIEW имеет следующий вид:
CREATE VIEW имя_представления [(имя_колонки, …)] AS запрос
имя_представления – именует представление. Имя не должно совпадать с именами существующих в базе данных таблиц и представлений.
имя_колонки – именует колонку представления. Если указывается список имен колонок, он должен содержать столько имен, сколько колонок определено в результирующей таблице запроса. Каждое имя_колонки должно быть уникальным и не уточненным. Если список имен колонок не указан, колонки представления наследуют имена колонок результирующей таблицы запроса. Список имен колонок должен быть указан, если результирующая таблица запроса имеет несколько колонок с одинаковыми именами или неименованные колонки.
AS – указывает начало определения представления.
запрос – определяет представление. В любой момент времени представление содержит строки, получающиеся в результате выполнения предложения SELECT. Запрос не может содержать в конструкции FROM предложения, изменяющие данные.
Примеры
Пример 1. Создать представление с именем MA_PROJ на таблице PROJECT, содержащее только те строки, в которых номер проекта (PROJNO) начинается буквами 'MA'.
CREATE VIEW MA_PROJ
AS
SELECT * FROM PROJECT
WHERE SUBSTR(ProjNo, 1, 2) = ’MA’
Пример 2. Создать представление, как и в примере 1, но включить в него только колонки для номера проекта (ProjNo), имени проекта (ProjName) и сотрудника, ответственного за проект (RespEmp).
CREATE VIEW MA_PROJ
AS
SELECT ProjNo, ProjName, RespEmp
FROM PROJECT
WHERE ProjNo LIKE ’MA%’
Пример 3. Создать представление, как и в примере 2, но в представлении назвать колонку сотрудника, отвечающего за проект, как IN_CHARGE.
CREATE VIEW MA_PROJ (PROJNO, PROJNAME, IN_CHARGE)
AS
SELECT PROJNO, PROJNAME, RESPEMP
FROM PROJECT
WHERE SUBSTR(PROJNO, 1, 2) = ’MA’
Примечание: даже если изменяется имя только одной колонки, в скобках за именем представления должны быть указаны имена всех трех колонок.
Это представление может быть создано и следующим образом:
CREATE VIEW MA_PROJ
AS
SELECT PROJNO, PROJNAME, RESPEMP AS IN_CHARGE
FROM PROJECT
WHERE SUBSTR(PROJNO, 1, 2) = ’MA’
Пример 4. Создать представление с именем PRJ_LEADER, которое содержит первые четыре колонки (PROJNO, PROJNAME, DEPTNO, RESPEMP) из таблицы PROJECT и фамилию (LASTNAME) сотрудника, отвечающего за проект (RESPEMP). Фамилию сотрудника можно получить из таблицы EMPLOYEE, используя соответствующие значения номера сотрудника EMPNO из таблицы EMPLOYEE и номера сотрудника RESPEMP из таблицы PROJECT.
CREATE VIEW PRJ_LEADER
AS
SELECT PROJNO, PROJNAME, DEPTNO, RESPEMP, LASTNAME
FROM PROJECT, EMPLOYEE
WHERE RESPEMP = EMPNO
Пример 5. Создать представление, как и в примере 4, но добавить к колонкам PROJNO, PROJNAME, DEPTNO, RESPEMP и LASTNAME величину общих выплат (SALARY + BONUS + COMM) для сотрудника, ответственного за проект. Кроме того, выбрать только те проекты, для которых значение штата сотрудников (PRSTAFF) больше единицы.
CREATE VIEW PRJ_LEADER (PROJNO, PROJNAME, DEPTNO, RESPEMP, LASTNAME,
TOTAL_PAY)
AS
SELECT PROJNO, PROJNAME, DEPTNO, RESPEMP, LASTNAME, SALARY+BONUS+COMM
FROM PROJECT, EMPLOYEE
WHERE RESPEMP = EMPNO AND PRSTAFF > 1
Список имен колонок представления может быть получен из списка имен колонок результирующей таблицы запроса, если в списке вывода SELECT для выражения SALARY+BONUS+COMM указать имя TOTAL_PAY.
CREATE VIEW PRJ_LEADER
AS
SELECT PROJNO, PROJNAME, DEPTNO, RESPEMP, LASTNAME,
SALARY+BONUS+COMM AS TOTAL_PAY
FROM PROJECT, EMPLOYEE
WHERE RESPEMP = EMPNO AND PRSTAFF > 1
