Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Диго С.М. Базы данных- проектирование и использ...doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
11.64 Mб
Скачать

Определение домена

Домен позволяет определить альтернативный тип данных. Домен создается оператором CREATE DOMAIN:

CREATE DOMAIN имя домена [AS] тип данных

[DEFAULT значение по умолчанию]

[определение ограничения...]

[COLLATE имя сравнения];

Домен имеет смысл создавать, когда определенный с его помо­щью тип данных используется в создаваемой базе данных многократ­но. При описании таблицы для соответствующих полей вместо типа данных будет указываться имя домена.

7.8.2. Запросы Оператор select

Общая характеристика оператора. Для отбора информации из базы данных служит оператор SELECT. Синтаксис оператора выгля­дит следующим образом:

SELECT [DISTINCT]

{{функция агрегирования.. | выражение для вычисления значения

[AS имя столбца]}.,}

| {спецификатор.*}

|*

FROM {{имя таблицы [А8][имя корреляции].[(имя столбца.,..)]}

|{подзапрос [АS][имя корреляции.[имя столбца.,..]}

|соединенная таблица}.,..

[WHERE предикат ]

[GROUP BY {{[ имя таблицы| имя корреляции]}.] имя столбца}.,..}]

[HAVING предикат]

[UNION | INTERSECT | EXCEPT}[ALL]

[CORRESPONDING [BY (имя столбца.,..)]]

оператор select | TABLE имя таблицы | конструктор значений таб­лицы]

[ORDER ВY{{столбец-результат [ASC| DESC]}.,..}

|{{положительное 4hoio[ASC| DESC]}.,..}]};

Оператор состоит из предложений SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, которые должны быть записаны в команде именно в той последовательности, в которой они перечисле­ны в синтаксической формуле.

Предложение SELECT. Оно определяет столбцы таблицы, полу­чаемой в результате выполнения запроса. Столбец результатной таб­лицы может быть задан именем столбца исходной таблицы. Если в запросе используется несколько таблиц и в них имеются поля, имею­щие одинаковые имена, то для указания такого поля используется кон­струкция <имя таблицы>.<имя поля>. Кроме того, в предложении SELECT могут использоваться любые допустимые выражения, кото­рые зададут формулу для определения вычисляемого поля. С помо­щью [AS <имя столбца>] можно задать имя столбца-результата. Эту конструкцию можно использовать не только тогда, когда определяются вычисляемые поля, но и во всех других случаях, когда нужно задать имя столбца-результата, отличающееся от имени столбца ис­ходной таблицы.

Результат выборки может в принципе содержать повторяющиеся строки. Чтобы избежать вывода повторяющихся строк в ответе, ис­пользуется параметр DISTINCT.

Запросы могут использовать функции агрегирования. Стандарт предусматривает использование следующих функций агрегирования:

  • COUNT - подсчет;

  • SUM - сумма;

  • МАХ -максимум;

  • MIN - минимум;

  • AVG - среднее.

Чаще всего функции агрегирования используются совместно с предложением GROUP BY, но могут применяться и самостоятельно. В последнем случае результат относится не к какой-то группе, а ко всей выборке.

Существуют два типа функции COUNT. Первый тип использует символ «*». В этом случае функция подсчитывает количество строк в группе. Отдельные значения столбцов при этом не учитываются, и результат не будет зависеть от того, имеются ли в полях значения Null и указан ли параметр DISTINCT. Второй тип функции COUNT игно­рирует значения Null.

Если в ответ требуется включить все поля таблицы, то для этого можно использовать символ «*». Если запрос многотабличный, то следует применять конструкцию {спецификатор.*}

Предложение FROM. В нем указываются таблицы, которые ис­пользуются при формулировании запроса. Кроме этого, в качестве источника данных в запросе могут быть заданы представления.

Начиная со стандарта SQL-92 в предложение FROM можно вклю­чать встроенный оператор JOIN, который служит для задания разно­образных условий соединения таблиц, участвующих в запросе.

Типы соединения и выполняемые ими действия приведены ниже.

В качестве примера для иллюстрации различных типов соедине­ний рассмотрена условная софтверная фирма X, которая продает про­граммные продукты. Причем это могут быть разработки как сотруд­ников фирмы, так и сторонних авторов.

Тип соединения

Выполняемое действие

Cross (перекрестное)

Прямое декартово произведение

Natural (естественное)

Соединение внешнего ключа со связанным с ним ключом (одноименные столбцы)

Inner (включающее или внутреннее)

Эквисоединение таблиц А и В (равные значения соответствующих столбцов)

Left (левое (внешнее))

Все строки таблицы А, а также значения из тех строк таблицы В,

которые имеют совпадающие значения в поле связи

Right (правое (внешнее))

Все строки таблицы В, а также значения из тех строк таблицы А,

которые имеют совпадающие значения в поле связи

Full (полное)

Объединяет левое и правое соединения

Union (соединение типа объединение)

Противоположно Inner

Таблица «А_сотрудники» содержит сведения о сотрудниках фир­мы X:

Таб_ном

ФИО

01

Диго

02

Афанасьев

03

Сидоров

Таблица «Б_разработки» содержит информацию о том, какие ПП предлагаются для распространения на фирме X и кто является авто­ром каждой разработки. Поскольку для сторонних разработчиков нет табельного номера (поле «А_сотрудники.таб_ном»), то в таблице «Б_разработки» фиксируются ФИО разработчиков.

ФИО

Продукт

Диго

П1

Диго

П2

Афанасьев

П3

Чистов

П4

Достаточно трудно определить предметную область, чтобы при­мер был не громоздкий и все теоретически возможные соединения имели реальную интерпретацию, поэтому некоторые примеры могут показаться несколько надуманными.

Если в предложении FROM перечислено несколько таблиц, то все они неявно считаются соединяемыми. Если тип соединения явно не задан, то считается, что каждая строка первой таблицы соединяется с каждой строкой второй таблицы. Именно такое соединение и называ­ется перекрестным.

Результат перекрестного соединения для приведенных выше таб­лиц представлен ниже.

Таб_ном

А_сотрудники.фио

Б_разработки.фио

Продукт

01

Диго

Диго

П1

01

Диго

Диго

П2

01

Диго

Афанасьев

ПЗ

01

Диго

Чистов

П4

02

Афанасьев

Диго

П1

02

Афанасьев

Диго

П2

02

Афанасьев

Афанасьев

ПЗ

02

Афанасьев

Чистов

П4

03

Сидоров

Диго

Ш

03

Сидоров

Диго

П2

03

Сидоров

Афанасьев

ПЗ

03

Сидоров

Чистов

П4

Запрос на SQL может иметь следующий вид:

SELECT а_сотрудники.таб_ном, а_сотрудники.фио, б_разработки.

фио, б_разработки.продукт

FROM а_сотрудники, б_разработки;

Чаще всего при создании запросов используется тип соединения INNER JOIN, при котором соединенная таблица будет включать толь­ко те строки, для которых есть соответствующие друг другу значения полей связи в обеих таблицах.

Результат соединения типа INNER JOIN для приведенных выше таблиц представлен ниже.

Таб_ном

ФИО

Продукт

01

Диго

П2

01

Диго

П1

02

Афанасьев

ПЗ

Этот запрос показывает разработки, выполненные сотрудниками фирмы X.

На SQL такой запрос будет иметь следующий вид:

SELECT а_сотрудники.таб_ном, а_сотрудники.фио, б_разработки.продукт

FROM а_сотрудники INNER JOIN б_разработки

ON а_сотрудники.фио = б_разработки.фио;

При использовании соединения типа LEFT JOIN в результатную таблицу попадают все записи из первой таблицы и только те записи из второй таблицы, для которых есть соответствующие значения по­лей связи в первой таблице. Соединение типа LEFT JOIN для рас­сматриваемого примера даст в результате список всех сотрудников фирмы X с указанием их разработок:

Таб_ном

ФИО

Продукт

01

Диго

П2

01

Диго

Ш

02

Афанасьев

ПЗ

03

Сидоров

Null

На SQL такой запрос будет выглядеть следующим образом:

SELECT а_сотрудники.таб_ном, а_сотрудники.фио, б_разработки.продукт

FROM а_сотрудники LEFT JOIN б_разработки

ON а_сотрудники.фио = б_разработки.фио;

При использовании соединения типа RIGHT JOIN, напротив, в результатную таблицу попадают все записи из второй таблицы и только те записи из первой таблицы, для которых есть соответствующие зна­чения полей связи во второй таблице. Соединение типа LEFT JOIN для рассматриваемого примера даст в результате список всех продук­тов с указанием разработчика и его табельного номера:

Таб_ном

ФИО

Продукт

01

Диго

Ш

01

Диго

П2

02

Афанасьев

ПЗ

Чистов

П4

На SQL такой запрос будет выглядеть следующим образом:

SELECT а_сотрудники.таб_ном, б_разработки.фио, б_разработки.продукт

FROM а_сотрудники RIGHT JOIN б_разработки

ON а_сотрудники.фио = б_разработки.фио;

Во всех приведенных выше примерах предполагалось, что усло­вием соединения является равенство значений полей связи. Обычно именно этот тип сравнения и используется.

Как уже указывалось, все возможности стандартного SQL в пол­ном объеме практически не реализованы ни в одной СУБД. Операто­ры INNER, LEFT, RIGHT JOIN присутствуют во многих системах, чего нельзя сказать о FULL и UNION JOIN.

FULL JOIN для нашего примера даст следующий результат:

Таб_ном

ФИО

Продукт

01

Диго

П1

01

Диго

П2

02

Афанасьев

ПЗ

03

Сидоров

Null

Null

Чистов

П4

Результатом UNION JOIN будет

Таб_ном

ФИО

Продукт

03

Сидоров

Null

Null

Чистов

П4

Предложение WHERE. В нем задается условие отбора записей. Предикат может включать одно выражение или несколько. Части слож­ного условия соединяются логическими операторами AND (И) или OR (ИЛИ).

В выражениях могут использоваться следующие операторы срав­нения: = (равно), о (не равно), < (меньше), <= (меньше или равно), > (больше), >= (больше или равно), которые могут предваряться опера­тором NOT.

Предикат может принимать одно из трех значений: TRUE, FALSE, UNKNOWN. В результатную таблицу переносятся те строки, для ко­торых значение предиката равно TRUE.

Кроме стандартных операторов сравнения в SQL можно исполь­зовать специальные операторы предикатов:

  • <интервальный предикат >;

  • <предикат Ш>;

  • < предикат проверки на неопределенное значение >;

  • <предикат подобия>.

При использовании интервального предиката диапазон значений можно задавать в виде

WHERE [NОТ]<выражение> BETWEEN <нижнее выражение> AND <верхнее выражение>.

Например, если требуется выдать сведения о поставке продукции за последнюю декаду ноября 2002 г., то запрос можно задать следую­щим образом:

SELECT * FROM post WHERE postdate BETWEEN #11/20/02# AND #11/30/02#;

Это же условие отбора можно задать и без использования интер­вального предиката:

postdate>=#11/20/02# AND postdate<= #11/30/02#;

При использовании предиката IN предложение WHERE будет иметь следующий вид:

WHERE [NOT]< выражение > [NOT] IN (<список значений>/<лод-запрос>).

В приведенном ниже примере требуется вывести данные о по­ставках поставщиков PI, P2, РЗ.

SELECT * FROM post WHERE kod_post IN ("p1", "p2", "p3")

Без использования IN запрос имел бы следующий вид:

SELECT * FROM post WHERE kod_post ="p1" OR kod_post ="p2" OR kod_post = "p3";

Пример с использованием подзапроса будет рассмотрен позже, при демонстрации возможностей обработки нескольких таблиц.

Предикат подобия применяется для поиска подстроки в указан­ной строке. Предложение WHERE при использовании предиката это­го типа будет иметь следующий вид:

WHERE [NOT] <выражение_для_вычисления_значения_строки_1>

[NOT] LIKE <выражение_для_вычисления_значения_строки_2>.

В качестве <выражения_для_вычисления_значения_строки_1> обычно используется <имя колонки>.

<Выражение_для_вычисления_значения_строки_2> называется образцом. В образце разрешается применять заполнители (трафарет­ные символы):

  • символ подчеркивания (_) - используется вместо любого еди­ничного символа в проверяемом значении;

  • символ процента (%) - заменяет набор любых символов в про­веряемом значении.

Предположим, что коды металлов начинаются с буквы «м». Тогда запрос, позволяющий вывести сведения о поставке металлов, будет иметь вид

SELECT * FROM post WHERE kod_mat LIKE "м%";

Предикат проверки на неопределенное значение имеет вид

предикат NULL ::=

конструктор значения строки IS [NOT] NULL

Например, если в таблице «Сотрудник» (sotr) есть поле «Ученая_степень» (ych_st), то запрос, выводящий список сотрудников, не имею­щих ученых степеней, будет выглядеть следующим образом:

SELECT fio FROM sotr WHERE ych_st IS NULL;

При использовании подзапросов в условии WHERE может быть использован квантор существования EXISTS. Формат условия WHERE в этом случае имеет вид

WHERE [NOT] EXISTS

(<подзапрос>).

EXISTS проверяет, вернул ли подзапрос какие-либо ряды. Факти­чески любой подзапрос, который может быть выражен с использова­нием IN, может альтернативным образом быть сформулирован также с использованием EXISTS. Обратное утверждение несправедливо.

Пример запроса с использованием EXISTS:

SELECT naimmat

FROM cennik

WHERE EXISTS

(SELECT *

FROM post

WHERE kodpost='P01' AND

cennik.kodmat=post.kodmat);

Предложение GROUP BY. Оно используется для определения групп выходных строк, к которым могут применяться те или иные агрегатные функции. Предложение GROUP BY всегда используется со встроенными агрегатными функциями. Обратное утверждение не­верно. Агрегатные функции могут использоваться в предложениях SELECT, HAVING. Если агрегатные функции используются без пред­ложения GROUP BY, то они будут применяться ко всему набору строк, удовлетворяющему условию запроса.

Конструкция GROUP BY работает только на одном уровне. Нельзя разбить каждую из этих групп на группы более низкого уровня, а за­тем применять стандартную функцию на каждом уровне подчинен­ности.

Например, в таблице «Zarpl», содержащей сведения о заработной плате рабочих, имеются колонки FIO (фамилия, инициалы), «ТаЬпош» (табельный номер), «Uch» (участок), «Zpl» (заработная плата). Требу­ется определить среднюю заработную плату по каждому участку:

SELECT uch, AVG(zpI)

FROM zarple

GROUP BY uch;

В данном примере рассматривается группировка по одной колон­ке. В принципе можно группировать строки таблицы по любой ком­бинации ее колонок. В этом случае имена колонок в предложении GROUP BY перечисляются через запятую.

Фраза GROUP BY означает логическую перекомпоновку (груп­пировку) таблицы по указанной колонке (колонкам). Физически таб­лицы в базе данных не перекомпоновываются. Логика выполнения запроса при использовании GROUP BY несколько отличается от реа­лизации обычного запроса. Фраза SELECT при использовании GROUP BY применяется к каждой группе, а не к каждой строке, как обычно.

Каждое выражение во фразе SELECT должно принимать един­ственное значение для группы, т.е. оно может быть либо самой ко­лонкой, либо арифметическим выражением, включающим эту колон­ку, либо агрегатной функцией, которая получает в результате един­ственное значение для группы. Кроме того, в SELECT может быть включена константа.

Предложение HAVING. Вместе с GROUP BY может использо­ваться фраза HAVING, которая для групп имеет то же значение, что и фраза WHERE - для строк.

Например, запрос на выдачу списка кодов тех материалов, по ко­торым было выполнено более чем по одной поставке, будет выгля­деть следующим образом:

SELECT codmat

FROM post

GROOUP BY codmat

HAVING COUNT(*)>1;

Выражение во фразе HAVING должно принимать единственное значение для группы. Формат COUNT(*) означает подсчет всех строк таблицы.

Предложение ORDER BY. Информация, получаемая в результа­те реализации запроса, может быть упорядочена. Для этого использу­ется фраза ORDER BY. Строки сортируются в соответствии со значе­ниями столбцов, указанных в списке. В этом списке могут задаваться либо имена колонок, либо целое число, которое соответствует номе­ру колонки в таблице, считая слева направо. Когда колонки, по кото­рым осуществляется упорядочение, вычисляемые или являются ре­зультатом операции UNION, то «целое» должно использоваться вме­сто имени колонки.

Параметр ASC/DESC означает вид сортировки (по возрастанию /по убыванию соответственно). По умолчанию принимается значение ASC.

Если в ORDER BY специфицируется список полей, то это означа­ет упорядочение по составному ключу. Старшинство полей сортировки будет определяться порядком следования полей в списке.

Колонки, специфицированные в ORDER BY, должны быть вклю­чены в SELECT.