Как мы уже отмечали ранее, к спецификации языка SQL можно относиться как к спецификации некоторой
Теперь следует понять, где хранятся эти данные.
Понятие
Забегая вперед (см. следующие лекции), следует заметить, что порождаемые таблицы SQL, которые формируются при выполнении запросов к SQL-ориентированной базе данных, еще более отдаляют SQL от реляционной модели. В таких таблицах может отсутствовать и правильно сформированный заголовок (могут иметься одноименные столбцы).
Почему же, понимая принципиальные отклонения языка SQL от
В специфицируются не только столбцы таблицы, но и
. Для изменения определения . Уничтожить хранимую таблицу (отменить ее определение) можно с помощью оператора .
Замечание: хотя внешне операторы , и похожи на соответствующие операторы определения, изменения определения и отмены определения домена, между ними имеется принципиальное различие. Определение домена приводит всего лишь к созданию некоторых новых
Оператор создания имеет следующий синтаксис:
base_table_element ::= column_definition | base_table_constraint_definition
Здесь base_table_name задает имя новой (изначально пустой)
Элемент
column_definition ::= column_name
{ data_type | domain_name }
[ default_definition ]
[ column_constraint_definition_list ]
В элементе column_name задает имя определяемого столбца. Тип столбца специфицируется путем явного указания типа данных ( data_type ) или путем указания имени ранее определенного домена ( domain_name ).
Необязательный раздел определения
DEFAULT { literal | niladic_function | NULL }
Действующее
DEFAULT, то DEFAULT, то NULL по умолчанию как явным, так и неявным образом, эти два случая не являются эквивалентными. Явное задание NULL в качестве Заметим, что если NULL ), но среди (см. ниже), то считается, что у столбца вообще отсутствует
Элемент необязательного списка
column_constraint_definition ::=
[ CONSTRAINT constraint_name ]
NOT NULL
| { PRIMARY KEY | UNIQUE }
| references_definition
| CHECK ( conditional_expression )
Как мы увидим немного позже, любое ограничение целостности, включаемое в
Ограничение означает, что в определяемом столбце никогда не должны содержаться неопределенные значения. Если определяемый столбец имеет имя C, то это ограничение эквивалентно следующему табличному ограничению: CHECK (C IS NOT NULL).
В (NULL = NULL) = true и что (a = NULL) = (NULL = a) = false для любого значения a, отличного от NULL ., в дополнение к этому, влечет за собой ограничение для определяемого столбца. Эти ограничения столбца эквивалентны следующим табличным ограничениям: и .
Ограничение references_definition означает объявление определяемого столбца
references_definition ::=
REFERENCES base_table_name [ (column_commalist) ]
[ MATCH { SIMPLE | FULL | PARTIAL } ]
[ ON DELETE referential_action ]
[ ON UPDATE referential_action ]
На самом деле, данная синтаксическая конструкция работает и в случае column_commalist может содержать имя только одного столбца (потому что внешний ключ состоит из одного определяемого столбца). Ограничение эквивалентно следующему табличному ограничению: .
CHECK (conditional_expression) приводит к тому, что в данном столбце могут находиться только те значения, для которых вычисление conditional_expression не приводит к результату false. В условном выражении
Элемент
base_table_constraint_definition ::=
[ CONSTRAINT constraint_name ]
{ PRIMARY KEY | UNIQUE } ( column_commalist )
| FOREIGN KEY ( column_commalist )
references_definition
| CHECK ( conditional_expression )
Как мы видим, имеется три разновидности табличных ограничений: или ), ) и CHECK ). Любому ограничению может явным образом назначаться имя, если перед определением ограничения поместить конструкцию .
, в дополнение к этому, влечет ограничение для всех столбцов, упоминаемых в определении ограничения. В определении таблицы допускается произвольное число определений
CHECK (conditional_expression) приводит к тому, что указанное false. Другими словами, таблица находится в соответствии с данным false.
Мы отложим обсуждение допустимых разновидностей SELECT языка SQL.
Синтаксис и семантика определения
Табличное ограничение означает объявление column_commalist. Обсудим теперь смысл references_definition ). Для удобства повторим синтаксическое правило.
references_definition ::=
REFERENCES base_table_name [ (column_commalist) ]
[ MATCH { SIMPLE | FULL | PARTIAL } ]
[ ON DELETE referential_action ]
[ ON UPDATE referential_action ]
В этом определении base_table_name должно представлять собой имя некоторой T ). Если определение ссылок включает список столбцов ( column_commalist ), то этот список должен совпадать (с точностью до порядка следования имен столбцов) со списком имен столбцов, использованных в некотором определении первичного или PRIMARY KEY или ) в определении таблицы T. Если в определении ссылок список столбцов явно не задан, то считается, что он совпадает со списком столбцов, использованных в определении PRIMARY KEY ) таблицы T.
Пусть определяемая таблица имеет имя S. Обсудим смысл необязательного раздела определения . Если этот раздел отсутствует или если присутствует и имеет вид , то S выполняется одно из следующих условий:
NULL ;T содержит в точности одну строку, такую, что значение S совпадает со значением соответствующего T.Если раздел присутствует в определении , то S выполняется одно из следующих условий:
NULL ;T содержит по крайней мере одну такую строку, что для каждого столбца данной строки таблицы S, значение которого отлично от NULL, его значение совпадает со значением соответствующего столбца T.Если раздел имеет вид , то S выполняется одно из следующих условий:
NULL ;NULL, и таблица T содержит в точности одну строку, такую, что значение S совпадает со значением соответствующего T.Очевидно, что только при наличии спецификации
В связи с определением ON DELETE referential_action и ON UPDATE referential_action. Прежде всего, приведем синтаксическое правило:
referential_action ::=
{ NO ACTION | RESTRICT | CASCADE
| SET DEFAULT | SET NULL }
Чтобы объяснить, в каких случаях и каким образом выполняются эти действия, требуется сначала определить понятие ссылающейся строки ( ясно следует, что в этом случае одна строка таблицы S может являться ссылающейся на несколько разных строк таблицы T .
Теперь приступим к ON DELETE referential_action. Предположим, что предпринимается попытка удалить строку t из таблицы T. Тогда:
NO ACTION или RESTRICT , то операция удаления отвергается, если ее выполнение вызвало бы нарушение CASCADE , то строка t удаляется, и если в определении MATCH или присутствуют спецификации MATCH SIMPLE или MATCH FULL, то удаляются все строки, ссылающиеся на t. Если же в определении MATCH PARTIAL, то удаляются только те строки, которые ссылаются исключительно на строку t ;SET DEFAULT , то строка t удаляется, и во всех столбцах, которые входят в состав t, проставляется заданное при их определении MATCH PARTIAL, то подобному воздействию подвергаются только те строки таблицы S, которые ссылаются исключительно на строку t ;SET NULL , то строка t удаляется, и во всех столбцах, которые входят в состав t, проставляется NULL. Если в определении MATCH PARTIAL, то подобному воздействию подвергаются только те строки таблицы S, которые ссылаются исключительно на строку t.Пусть определение ON UPDATE referential_action. Предположим, что предпринимается попытка обновить столбцы соответствующего t из таблицы T. Тогда:
NO ACTION или RESTRICT , то операция обновления отвергается, если ее выполнение вызвало бы нарушение СASCADE, то строка t обновляется, и если в определении MATCH или присутствуют спецификации MATCH SIMPLE или MATCH FULL, то соответствующим образом обновляются все строки, ссылающиеся на t (в них должным образом изменяются значения столбцов, входящих в состав MATCH PARTIAL, то обновляются только те строки, которые ссылаются исключительно на строку t ;SET DEFAULT , то строка t обновляется, и во всех столбцах, которые входят в состав T, всех строк, ссылающихся на строку t, проставляется заданное при их определении MATCH PARTIAL, то подобному воздействию подвергаются только те строки таблицы S, которые ссылаются исключительно на строку t, причем в них изменяются значения только тех столбцов, которые не содержали NULL ;Определим таблицы служащих ( ), отделов ( DEPT ) и проектов ( ). Эти таблицы имеют заголовки, показанные на рис. 12.1.
(рис 12.1) Заголовки таблиц EMP, DEPT и PROСтолбцы EMP_NO, EMP_SAL, DEPT_NO, PRO_NO, DEPT_TOTAL_SAL, DEPT_MNG и PRO_MNG определяются на ранее определенных доменах (определения доменов EMP_NO и SALARY приведены в предыдущей лекции). , DEPT и проектов являются столбцы EMP_NO, DEPT_NO и PRO_NO соответственно. В таблице столбцы DEPT_NO и PRO_NO являются внешними ключами, указывающими на отдел, в котором работает служащий, и на выполняемый им проект соответственно. В таблице DEPT DEPT_MNG, указывающий на служащего, являющегося руководителем соответствующего отдела, а в таблице PRO_MNG, указывающий на служащего, являющегося менеджером соответствующего проекта. Другие
Определим таблицу :
(1) CREATE TABLE EMP (
(2) EMP_NO EMP_NO PRIMARY KEY,
(3) EMP_NAME VARCHAR(20) DEFAULT 'Incognito' NOT NULL,
(4) EMP_BDATE DATE DEFAULT NULL CHECK (
VALUE >= DATE '1917-10-24'),
(5) EMP_SAL SALARY,
(6) DEPT_NO DEPT_NO DEFAULT NULL REFERENCES
DEPT ON DELETE SET NULL,
(7) PRO_NO PRO_NO DEFAULT NULL,
(8) FOREIGN KEY PRO_NO REFERENCES PRO (PRO_NO)
ON DELETE SET NULL,
(9) CONSTRAINT PRO_EMP_NO CHECK
((SELECT COUNT (*) FROM EMP E
WHERE E.PRO_NO = PRO_NO) <= 50));
Последовательно обсудим части этого определения. В части (1) указывается, что создается таблица с именем . В части (2) определяется столбец EMP_NO на домене EMP_NO. У этого столбца не определено AND к ограничениям, унаследованным столбцом от определения домена). Помимо прочего, это означает неявное указание запрета для данного столбца неопределенных значений. В части (3) определен столбец EMP_NAME на 'Incognito', и в качестве EMP_BDATE (дата рождения служащего). Он имеет тип данных DATE, NULL (даты рождения некоторых служащих неизвестны). Кроме того, ограничение столбца запрещает принимать на работу лиц, о которых известно, что они родились до Октябрьского переворота. В части (5) определен столбец EMP_SAL на домене SALARY. DEPT_NO определяется на одноименном домене (для наших целей его определение несущественно), но явно объявляется, что NULL (некоторые служащие не приписаны ни к какому отделу). Кроме того, добавляется DEPT_NO ссылается на первичный ключ таблицы DEPT. Определено DEPT во всех строках таблицы , ссылавшихся на эту строку, столбцу DEPT_NO должно быть присвоено неопределенное значение. В части (7) определяется столбец PRO_NO. Его определение аналогично DEPT_NO, но PRO_EMP_NO, которое требует, чтобы ни в одном проекте не участвовало больше 50 служащих (правила построения соответствующего
Определим таблицу DEPT:
(1) CREATE TABLE DEPT (
(2) DEPT_NO DEPT_NO PRIMARY KEY,
(3) DEPT_EMP_NO INTEGER NOT NULL CHECK (
VALUE BETWEEN 1 AND 100),
(4) DEPT_NAME VARCHAR(200) DEFAULT 'Nameless' NOT NULL,
(5) DEPT_TOTAL_SAL SALARY DEFAULT 1000000.00
NOT NULL CHECK (VALUE > = 100000.00),
(6) DEPT_MNG EMP_NO DEFAULT NULL
REFERENCES EMP ON DELETE SET NULL
CHECK (IF (VALUE IS NOT NULL) THEN
((SELECT COUNT(*) FROM DEPT
WHERE DEPT.DEPT_MNG = VALUE) = 1),
(7) CHECK (DEPT_EMP_NO =
(SELECT COUNT(*) FROM EMP
WHERE DEPT_NO = EMP.DEPT_NO)),
(8) CHECK (DEPT_TOTAL_SAL >=
(SELECT SUM(EMP_SAL) FROM EMP
WHERE DEPT_NO = EMP.DEPT_NO)));
Это определение мы обсудим в менее DEPT_MNG – часть (6). Этот столбец объявляется DEPT. Но мы хотим сказать больше. У отдела могут временно отсутствовать руководители, поэтому в столбце допускаются неопределенные значения. Но если у отдела имеется руководитель, то он должен являться руководителем только этого отдела. На первый взгляд можно было бы воспользоваться ограничением столбца . Но такое ограничение допускало бы наличие неопределенного столбца DEPT_MNG только в одной строке таблицы DEPT, а мы хотим допустить отсутствие руководителя у нескольких отделов. Поэтому потребовалось ввести более громоздкое
По поводу двух приведенных определений
На первый вопрос можно ответить следующим образом. Да, эти ограничения можно было бы включить в
Вот ответ на второй вопрос. Ограничение (9) в первом определении и ограничения (7) и (8) во втором определении внешне похожи, но сильно отличаются по своей сути. Ограничения (7) и (8) связаны с агрегатной семантикой столбцов DEPT_EMP_NO и DEPT_TOTAL_SAL таблицы DEPT. Отмена ограничений изменила бы смысл этих столбцов. Ограничение (9) является текущим административным ограничением. Если руководство предприятия примет решение разрешить использовать в одном проекте более 50 служащих, ограничение можно отменить без изменения смысла столбцов таблицы . Имея это в виду, мы ввели явное имя ограничения (9), чтобы при необходимости имелась простая возможность отменить это ограничение с помощью оператора .
Наконец, определим таблицу .
(1) CREATE TABLE PRO (
(2) PRO_NO PRO_NO PRIMARY KEY,
(3) PRO_TITLE VARCHAR(200)DEFAULT 'No title' NOT NULL,
(4) PRO_SDATE DATE DEFAULT CURRENT_DATE NOT NULL,
(5) PRO_DURAT INTERVAL YEAR DEFAULT INTERVAL '1'
YEAR NOT NULL,
(6) PRO_MNG EMP_NO UNIQUE NOT NULL
REFERENCES EMP ON DELETE NO ACTION,
(7) PRO_DESC CLOB(10M));
Столбец PRO_SDATE содержит дату начала проекта, а столбец PRO_DURAT – продолжительность проекта в годах. В этом определении имеет смысл прокомментировать часть (6). Мы считаем, что если отдел, по крайней мере временно, может существовать без руководителя, то у проекта всегда должен быть менеджер. Поэтому PRO_MNG является гораздо более строгим, чем DEPT_MNG в таблице DEPT. Сочетание ограничений и при отсутствии PRO_MNG. Другими словами, этот столбец обладает всеми характеристиками с соответствующим значением NO ACTION, запрещающим такие удаления. В совокупности это гарантирует, что у любого проекта будет существовать менеджер, являющийся служащим предприятия. В части (7) столбец PRO_DESC (описание проекта) определен как большой символьный объект с максимальным размером 10 Мбайт.
Оператор изменения определения имеет следующий синтаксис:
base_table_alteration ::= ALTER TABLE base_table_name
column_alteration_action
| base_table_constraint_alternation_action
Как видно из этого синтаксического правила, при выполнении одного оператора может быть выполнено либо действие по изменению
Действие по
column_alteration_action ::=
ADD [ COLUMN ] column_definition
| ALTER [ COLUMN ] column_name
{ SET default_definition | DROP DEFAULT }
| DROP [ COLUMN ] column_name
{ RESTRICT | CASCADE }
Итак, с использованием оператора можно добавлять к определению таблицы ADD ) и изменять или отменять и соответственно).
Смысл действия ADD COLUMN почти полностью совпадает со смыслом раздела . Указывается имя нового столбца, его тип данных или домен. Могут определяться ADD оператора , добавляется к уже существующей таблице, которая, скорее всего, содержит некоторый набор строк. В каждой из существующих строк новый столбец должен содержать некоторое значение, и считается, что сразу после выполнения действия ADD этим значением является ADD, обязательно должен иметь NULL ), но среди .
В действии можно изменить ( SET default_definition ) или отменить определение . Заметим, что изменение
Действие отменяет отвергается, если:
Если в действии присутствует спецификация , то его выполнение порождает неявное выполнение оператора для всех представлений и
Предположим, что на предприятии ввели систему премирования служащих. Каждый служащий может дополнительно к зарплате получать ежемесячную премию, не превышающую размер его зарплаты. Тогда разумно добавить к таблице новый столбец EMP_BONUS, используя оператор :
ALTER TABLE EMP ADD EMP_BONUS SALARY DEFAULT NULL CONSTRAINT BONSAL CHECK (VALUE < EMP_SAL);
Обратите внимание, что мы присвоили
При EMP_SAL таблицы для этого столбца явно не определялось
ALTER TABLE EMP ALTER EMP_SAL SET DEFAULT 15000.00.
При DEPT_TOTAL_SAL таблицы DEPT для него было установлено
ALTER TABLE DEPT ALTER DEPT_TOTAL_SAL DROP DEFAULT.
Обратите внимание, что после выполнения этого оператора при вставке новой строки в таблицу DEPT всегда потребуется явно указывать значение столбца DEPT_TOTAL_SAL. Хотя формально у столбца будет существовать SALARY (10000.00), оно не может быть занесено в таблицу DEPT, поскольку противоречит ограничению столбца DEPT_TOTAL_SAL CHECK (VALUE >= 100000.00).
Можно задуматься, действительно ли требуется поддерживать в таблице DEPT столбец DEPT_EMP_NO. Как мы видели, для его поддержки требуется проверять громоздкое ограничение целостности, а число служащих в любом отделе можно получить динамически с помощью простого запроса к таблице (собственно, этот запрос входит в ограничение целостности). Поэтому может оказаться разумным отменить DEPT_EMP_NO, выполнив следующий оператор :
ALTER TABLE DEPT DROP DEPT_EMP_NO CASCADE.
Напомним, что спецификация ведет к тому, что при выполнении оператора будет уничтожено не только DEPT_EMP_NO содержалась спецификация , поскольку это единственное внешнее определение ограничения является ограничением только столбца DEPT_EMP_NO.
Действие по
base_table_constraint_alternation_action ::=
ADD [ CONSTRAINT ] base_table_constraint_definition
| DROP CONSTRAINT constraint_name
{ RESTRICT | CASCADE }
Действие ADD [ позволяет добавить к набору существующих ограничений таблицы новое ограничение целостности. Можно считать, что новое ограничение добавляется через AND к . Но здесь имеется одно существенное отличие. Если внимательно посмотреть на все возможные виды табличных ограничений, можно убедиться, что любое из них удовлетворяется на пустой таблице. Поэтому, какой бы набор табличных ограничений ни был определен при . При добавлении нового табличного ограничения с использованием действия ADD [ мы имеем другую ситуацию, поскольку таблица, скорее всего, уже содержит некоторый набор строк, для которого false. В этом случае выполнение оператора , включающего действие ADD [ , отвергается.
Выполнение действия . действие отвергается, если на данный возможный ключ ссылается хотя бы один внешний ключ. При указании действие выполняется в любом случае, и все определения таких
Напомним, что мы добавили к таблице столбец EMP_BONUS, в котором сохраняются размеры ежемесячных премий служащих. Предположим, что премии выплачиваются из фонда DEPT_TOTAL_SAL, устанавливающее, что объем фонда зарплаты отдела не должен быть меньше суммарной зарплаты служащих этого отдела, становится недостаточным, и нам требуется добавить к набору ограничений таблицы DEPT новое ограничение:
ALTER TABLE DEPT ADD CONSTRAINT TOTAL_INCOME
CHECK (DEPT_TOTAL_SAL >=
(SELECT SUM(EMP_SAL + COALESCE(EMP_BONUS,0))
FROM EMP WHERE EMP.DEPT_NO = DEPT_NO)).
Хотя это ограничение на вид довольно сложное, смысл его очень прост: суммарный доход служащих отдела не должен превышать объем зарплаты отдела. В SUM используется операция COALESCE. Эта двуместная операция определяется следующим образом:
COALESCE (x, y) IF x IS NOT NULL THEN x ELSE y,
т. е. значением операции является значение первого операнда, если оно не равно NULL, и значение второго операнда – в противном случае. Нам пришлось воспользоваться этой операцией, поскольку в столбце EMP_BONUS допускается наличие неопределенных значений.
Понятно, что новое ограничение столбца DEPT_TOTAL_SAL сильнее предыдущего, и это предыдущее ограничение можно было бы отменить. Конечно, с логической точки зрения наличие обоих ограничений ничему не повредит (предыдущее ограничение является логическим следствием нового), но при использовании не слишком интеллектуальной реализации SQL может привести к замедлению работы системы, поскольку оба ограничения могут проверяться независимо. К сожалению, при определении таблицы мы не присвоили явное имя DEPT_TOTAL_SAL и поэтому не можем немедленно продемонстрировать оператор отмены этого ограничения. Это не значит, что его нельзя отменить вообще. В
Кстати, новому ограничению мы присвоили явное имя. К этому привели следующие рассуждения. Когда создавалась исходная
При определении таблицы было специфицировано PRO_EMP_NO, устанавливающее, что над одним проектом не должно работать более 50 служащих. Мы уже отмечали, что это ограничение носит чисто административный характер и может быть отменено без нарушения логики базы данных. Для отмены ограничения нужно выполнить следующий оператор:
ALTER TABLE EMP DROP CONSTRAINT PRO_EMP_NO;
Для отмены определения (уничтожения) , задаваемый в следующем синтаксисе:
DROP TABLE base_table_name { RESTRICT | CASCADE }
Успешное выполнение оператора приводит к тому, что указанная оператор выполняется в любом случае, и все определения представлений и
Виды
(рис 12.2) Иерархия видов ограничений целостностиНо иерархия видов , а мы их будем называть
Для определения , задаваемый в следующем синтаксисе:
CREATE ASSERTION constraint_name
CHECK (conditional_expression)
Заметим, что при создании
В определении таблицы содержалось ограничение столбца EMP_BDATE:
CHECK (EMP_BDATE >= '1917-10-24')
(к работе на предприятии допускаются только те лица, которые родились после Октябрьского переворота). Вот каким образом можно определить такое же ограничение на уровне
CREATE ASSERTION MIN_EMP_BDATE CHECK
(((SELECT MIN(EMP_BDATE)) FROM EMP) >= '1917-10-24')
В логическом условии этого общего ограничения выбирается минимальное значение столбца EMP_BDATE (дата рождения самого старого служащего). Значением false в том и только в том случае, если среди служащих имеется хотя бы один, родившийся до указанной даты.
Теперь переформулируем в виде , которое определялось следующим образом:
CONSTRAINT PRO_EMP_NO CHECK
((SELECT COUNT (*) FROM EMP E
WHERE E.PRO_NO = PRO_NO) <= 50)
(над одним проектом не может работать более 50 служащих).
Вот формулировка эквивалентного
CREATE ASSERTION NEW_PRO_EMP_NO CHECK
( NOT EXISTS (SELECT PRO_NO FROM EMP GROUP BY PRO_NO
HAVING COUNT(*) > 50)).
Логическое выражение этого ограничения может принимать только значения true и false. Внутренний оператор выборки группирует строки таблицы таким образом, что в одну группу попадают все строки с одинаковым значением столбца PRO_NO. Затем эти группы фильтруются по условию раздела HAVING, и остаются только группы, включающие более 50 строк. В результирующей таблице содержатся строки из одного столбца, содержащего значение PRO_NO оставшихся групп. Предикат NOT EXISTS принимает значение true тогда и только тогда, когда эта результирующая таблица не содержит ни одной строки, т. е. нет ни одного проекта, в котором работает больше 50 служащих.
Покажем, как можно сформулировать в виде PRO_NO, входящего в состав определения таблицы :
FOREIGN KEY PRO_NO REFERENCES PRO (PRO_NO)
В виде
(1) CREATE ASSERTION FK_PRO_NO CHECK
(2) ( NOT EXISTS (SELECT * FROM EMP
WHERE PRO_NO IS NOT NULL AND
(3) NOT EXISTS (SELECT * FROM PRO
(4) WHERE PRO.PRO_NO = EMP.PRO_NO))).
Логическое выражение этого ограничения выглядит достаточно сложным и нуждается в пояснении. Условие выборки оператора SELECT на строке (2) состоит из двух частей, связанных через AND. Первая часть отфильтровывает те строки таблицы , у которых в столбце PRO_NO содержится NULL. Если этот столбец содержит NULL во всех строках таблицы, то результирующая таблица оператора выборки на строке (2) будет пустой, и значением предиката NOT EXISTS будет true, т. е. ограничение удовлетворяется.
Теперь предположим, что в таблице cand_pro_no является допустимым значением
Если же найдется хотя бы одна строка таблицы с таким значением cand_pro_no столбца PRO_NO, что в таблице не найдется ни одной строки, значение столбца PRO_NO которой равнялось бы этому cand_pro_no, то результирующая таблица оператора выборки на строке (3) будет пустой, и значением предиката NOT EXISTS на строке (3) будет true. Тогда все условие выборки первого оператора SELECT примет значение true, и эта строка таблицы будет пропущена в результирующую таблицу. Значением предиката NOT EXISTS будет false, т. е. ограничение не удовлетворяется.
Мы сознательно привели такое подробное пояснение не только для того, чтобы прояснить смысл FK_PRO_NO, но и чтобы дать понять, во что реально вырождается простая синтаксическая конструкция определения
Наконец, сформулируем общее ограничение целостности, состоящее в том, что никакой
(1) CREATE ASSERTION PRO_MNG_CONSTR CHECK
(2) NOT EXISTS (SELECT * FROM EMP EMP1, EMP EMP2,
DEPT, PRO WHERE
(3) EMP1.EMP_NO = PRO.PRO_MNG AND
(4) EMP1.DEPT_NO = DEPT.DEPT_NO AND
(5) DEPT.DEPT_MNG = EMP2.EMP_NO AND
(6) EMP1.EMP_SAL + COALESCE (EMP1.EMP_BONUS,0) >
(7) EMP2.EMP_SAL + COALESCE (EMP2.EMP_BONUS,0);
В логическом выражении этого ограничения используется оператор выборки SELECT, в разделе перечня таблиц ( FROM ) впервые в этом курсе используется несколько таблиц. Такие запросы в SQL называются запросами с соединениями, и мы воспользуемся случаем, чтобы пояснить на примере (конечно, предварительно), как их следует понимать в соответствии со стандартом языка SQL.
Итак, в разделе FROM оператора выборки, используемого в логическом условии этого ограничения, через запятую перечислены четыре элемента – , , DEPT и . Выражение вида означает применение своего рода операции переименования. Внутри запроса столбцы этого "экземпляра" имеют "квалифицированные" имена вида ANOTHER_NAME.column_name, где column_name обозначает имя существующего столбца таблицы .
Вычисление оператора выборки начинается с того, что формируется расширенное
Условие раздела WHERE состоит из четырех частей, связанных через AND. Обсудим их последовательно. После проверки условия EMP1.EMP_NO = в таблице ALL_TOGETHER останутся все служащие-менеджеры проектов вместе со своими проектами в комбинации со всеми возможными отделами и всеми возможными служащими (назовем эту отфильтрованную таблицу ALL_TOGETHER_STEP1 ). После проверки условия EMP1.DEPT_NO = DEPT.DEPT_NO в таблице ALL_TOGETHER_STEP1 останутся все служащие-менеджеры проектов вместе со своими проектами и вместе с описанием своих отделов в комбинации со всеми возможными служащими (назовем эту отфильтрованную таблицу ALL_TOGETHER_STEP2 ). После проверки условия DEPT.DEPT_MNG = EMP2.EMP_NO в таблице ALL_TOGETHER_STEP2 останутся все служащие-менеджеры проектов вместе со своими проектами, вместе с описанием своих отделов и вместе с руководителями этих отделов (по одной строке для каждого допустимого сочетания " проект-менеджер_проекта-отдел_менеджера_проекта-руководитель_отдела_менеджера_проекта "). Назовем эту отфильтрованную таблицу ALL_TOGETHER_STEP3. Легко видеть, что после проверки условия EMP1.EMP_SAL + EMP1.EMP_BONUS > EMP2.EMP_SAL + EMP2.EMP_BONUS в таблице ALL_TOGETHER_STEP3 могут остаться только строки проект-менеджер_проекта-отдел_менеджера_проекта-руководитель_отдела_менеджера_проекта, в которых суммарный доход менеджера проекта превышает суммарный доход руководителя отдела, где работает NOT EXISTS будет false, и тем самым ограничение целостности PRO_MNG_CONSTR будет нарушено.
Для того чтобы отменить ранее определенное общее ограничение целостности, нужно воспользоваться оператором , задаваемым в следующем синтаксисе:
DROP ASSERTION constraint_name
Вот пример оператора, отменяющего определение дискриминационного PRO_MNG_CONSTR:
DROP ASSERTION PRO_MNG_CONSTR;
На первый взгляд кажется, что false при любой
CHECK (DEPT_EMP_NO =
(SELECT COUNT(*) FROM EMP
WHERE DEPT_NO = EMP.DEPT_NO))
из определения таблицы DEPT. Предположим, например, что в отдел зачисляется новый служащий. Тогда нужно выполнить две операции: (a) вставить новую строку в таблицу и (b) изменить соответствующую строку таблицы DEPT (прибавить единицу к значению столбца DEPT_EMP_NO ). Очевидно, что в каком бы порядке ни выполнялись эти операции, сразу после выполнения первой из них ограничение целостности будет нарушено, соответствующее действие будет отвергнуто, и мы никогда не сможем принять на работу нового служащего.
Поскольку
Для этого в качестве заключительной синтаксической конструкции к любому определению INITIALLY в следующей синтаксической форме:
INITIALLY { DEFERRED | IMMEDIATE }
[ [ NOT ] DEFERRABLE ]
Эта спецификация указывает, в каком режиме должно находиться данное ограничение целостности в начале выполнения любой транзакции ( и DEFFERABLE ). Если же возможный ключ используется в некотором определении NOT DEFFERABLE .
Комбинация INITIALLY DEFERRED NOT DEFERRABLE является недопустимой. Если в определении ограничения спецификация начального режима проверки отсутствует, то подразумевается наличие спецификации INITIALLY IMMEDIATE. При наличии явной или неявной спецификации INITIALLY IMMEDIATE и отсутствии явного указания возможности смены режима подразумевается наличие спецификации NOT DEFERRABLE. При наличии спецификации INITIALLY DEFERRED и отсутствии явного указания возможности смены режима подразумевается наличие спецификации DEFERRABLE.
При выполнении транзакции можно изменить режим проверки некоторых или всех , задаваемый в следующем синтаксисе:
SET CONSTRAINTS { constraint_name_commalist | ALL }
{ DEFERRED | IMMEDIATE }
Если в операторе указывается список имен DEFERRABLE ; если хотя бы для одного ограничения из списка это требование не выполняется, то операция отвергается. При указании ключевого слова ALL режим устанавливается для всех ограничений, в определении которых явно или неявно было указано DEFERRABLE. Если в качестве желаемого режима проверки ограничений задано DEFERRED, то все указанные ограничения переводятся в режим отложенной проверки. Если в качестве желаемого режима проверки ограничений задано IMMEDIATE, то все указанные ограничения переводятся в режим отвергается, и все указанные ограничения остаются в предыдущем режиме.
При выполнении операции COMMIT неявно выполняется операция SET CONSTRAINTS ALL IMMEDIATE. Если эта операция отвергается, то COMMIT срабатывает как ROLLBACK.
В этой и предыдущей лекциях мы обсудили наиболее важные аспекты языка SQL, связанные с определением схемы базы данных, – типы данных SQL, средства определения доменов,
Как мы уже отмечали ранее, к спецификации языка SQL можно относиться как к спецификации некоторой
Теперь следует понять, где хранятся эти данные.
Понятие
Забегая вперед (см. следующие лекции), следует заметить, что порождаемые таблицы SQL, которые формируются при выполнении запросов к SQL-ориентированной базе данных, еще более отдаляют SQL от реляционной модели. В таких таблицах может отсутствовать и правильно сформированный заголовок (могут иметься одноименные столбцы).
Почему же, понимая принципиальные отклонения языка SQL от
В специфицируются не только столбцы таблицы, но и
. Для изменения определения . Уничтожить хранимую таблицу (отменить ее определение) можно с помощью оператора .
Замечание: хотя внешне операторы , и похожи на соответствующие операторы определения, изменения определения и отмены определения домена, между ними имеется принципиальное различие. Определение домена приводит всего лишь к созданию некоторых новых
Оператор создания имеет следующий синтаксис:
base_table_element ::= column_definition | base_table_constraint_definition
Здесь base_table_name задает имя новой (изначально пустой)
Элемент
column_definition ::= column_name
{ data_type | domain_name }
[ default_definition ]
[ column_constraint_definition_list ]
В элементе column_name задает имя определяемого столбца. Тип столбца специфицируется путем явного указания типа данных ( data_type ) или путем указания имени ранее определенного домена ( domain_name ).
Необязательный раздел определения
DEFAULT { literal | niladic_function | NULL }
Действующее
DEFAULT, то DEFAULT, то NULL по умолчанию как явным, так и неявным образом, эти два случая не являются эквивалентными. Явное задание NULL в качестве Заметим, что если NULL ), но среди (см. ниже), то считается, что у столбца вообще отсутствует
Элемент необязательного списка
column_constraint_definition ::=
[ CONSTRAINT constraint_name ]
NOT NULL
| { PRIMARY KEY | UNIQUE }
| references_definition
| CHECK ( conditional_expression )
Как мы увидим немного позже, любое ограничение целостности, включаемое в
Ограничение означает, что в определяемом столбце никогда не должны содержаться неопределенные значения. Если определяемый столбец имеет имя C, то это ограничение эквивалентно следующему табличному ограничению: CHECK (C IS NOT NULL).
В (NULL = NULL) = true и что (a = NULL) = (NULL = a) = false для любого значения a, отличного от NULL ., в дополнение к этому, влечет за собой ограничение для определяемого столбца. Эти ограничения столбца эквивалентны следующим табличным ограничениям: и .
Ограничение references_definition означает объявление определяемого столбца
references_definition ::=
REFERENCES base_table_name [ (column_commalist) ]
[ MATCH { SIMPLE | FULL | PARTIAL } ]
[ ON DELETE referential_action ]
[ ON UPDATE referential_action ]
На самом деле, данная синтаксическая конструкция работает и в случае column_commalist может содержать имя только одного столбца (потому что внешний ключ состоит из одного определяемого столбца). Ограничение эквивалентно следующему табличному ограничению: .
CHECK (conditional_expression) приводит к тому, что в данном столбце могут находиться только те значения, для которых вычисление conditional_expression не приводит к результату false. В условном выражении
Элемент
base_table_constraint_definition ::=
[ CONSTRAINT constraint_name ]
{ PRIMARY KEY | UNIQUE } ( column_commalist )
| FOREIGN KEY ( column_commalist )
references_definition
| CHECK ( conditional_expression )
Как мы видим, имеется три разновидности табличных ограничений: или ), ) и CHECK ). Любому ограничению может явным образом назначаться имя, если перед определением ограничения поместить конструкцию .
, в дополнение к этому, влечет ограничение для всех столбцов, упоминаемых в определении ограничения. В определении таблицы допускается произвольное число определений
CHECK (conditional_expression) приводит к тому, что указанное false. Другими словами, таблица находится в соответствии с данным false.
Мы отложим обсуждение допустимых разновидностей SELECT языка SQL.
Синтаксис и семантика определения
Табличное ограничение означает объявление column_commalist. Обсудим теперь смысл references_definition ). Для удобства повторим синтаксическое правило.
references_definition ::=
REFERENCES base_table_name [ (column_commalist) ]
[ MATCH { SIMPLE | FULL | PARTIAL } ]
[ ON DELETE referential_action ]
[ ON UPDATE referential_action ]
В этом определении base_table_name должно представлять собой имя некоторой T ). Если определение ссылок включает список столбцов ( column_commalist ), то этот список должен совпадать (с точностью до порядка следования имен столбцов) со списком имен столбцов, использованных в некотором определении первичного или PRIMARY KEY или ) в определении таблицы T. Если в определении ссылок список столбцов явно не задан, то считается, что он совпадает со списком столбцов, использованных в определении PRIMARY KEY ) таблицы T.
Пусть определяемая таблица имеет имя S. Обсудим смысл необязательного раздела определения . Если этот раздел отсутствует или если присутствует и имеет вид , то S выполняется одно из следующих условий:
NULL ;T содержит в точности одну строку, такую, что значение S совпадает со значением соответствующего T.Если раздел присутствует в определении , то S выполняется одно из следующих условий:
NULL ;T содержит по крайней мере одну такую строку, что для каждого столбца данной строки таблицы S, значение которого отлично от NULL, его значение совпадает со значением соответствующего столбца T.Если раздел имеет вид , то S выполняется одно из следующих условий:
NULL ;NULL, и таблица T содержит в точности одну строку, такую, что значение S совпадает со значением соответствующего T.Очевидно, что только при наличии спецификации
В связи с определением ON DELETE referential_action и ON UPDATE referential_action. Прежде всего, приведем синтаксическое правило:
referential_action ::=
{ NO ACTION | RESTRICT | CASCADE
| SET DEFAULT | SET NULL }
Чтобы объяснить, в каких случаях и каким образом выполняются эти действия, требуется сначала определить понятие ссылающейся строки ( ясно следует, что в этом случае одна строка таблицы S может являться ссылающейся на несколько разных строк таблицы T .
Теперь приступим к ON DELETE referential_action. Предположим, что предпринимается попытка удалить строку t из таблицы T. Тогда:
NO ACTION или RESTRICT , то операция удаления отвергается, если ее выполнение вызвало бы нарушение CASCADE , то строка t удаляется, и если в определении MATCH или присутствуют спецификации MATCH SIMPLE или MATCH FULL, то удаляются все строки, ссылающиеся на t. Если же в определении MATCH PARTIAL, то удаляются только те строки, которые ссылаются исключительно на строку t ;SET DEFAULT , то строка t удаляется, и во всех столбцах, которые входят в состав t, проставляется заданное при их определении MATCH PARTIAL, то подобному воздействию подвергаются только те строки таблицы S, которые ссылаются исключительно на строку t ;SET NULL , то строка t удаляется, и во всех столбцах, которые входят в состав t, проставляется NULL. Если в определении MATCH PARTIAL, то подобному воздействию подвергаются только те строки таблицы S, которые ссылаются исключительно на строку t.Пусть определение ON UPDATE referential_action. Предположим, что предпринимается попытка обновить столбцы соответствующего t из таблицы T. Тогда:
NO ACTION или RESTRICT , то операция обновления отвергается, если ее выполнение вызвало бы нарушение СASCADE, то строка t обновляется, и если в определении MATCH или присутствуют спецификации MATCH SIMPLE или MATCH FULL, то соответствующим образом обновляются все строки, ссылающиеся на t (в них должным образом изменяются значения столбцов, входящих в состав MATCH PARTIAL, то обновляются только те строки, которые ссылаются исключительно на строку t ;SET DEFAULT , то строка t обновляется, и во всех столбцах, которые входят в состав T, всех строк, ссылающихся на строку t, проставляется заданное при их определении MATCH PARTIAL, то подобному воздействию подвергаются только те строки таблицы S, которые ссылаются исключительно на строку t, причем в них изменяются значения только тех столбцов, которые не содержали NULL ;Определим таблицы служащих ( ), отделов ( DEPT ) и проектов ( ). Эти таблицы имеют заголовки, показанные на рис. 12.1.
(рис 12.1) Заголовки таблиц EMP, DEPT и PROСтолбцы EMP_NO, EMP_SAL, DEPT_NO, PRO_NO, DEPT_TOTAL_SAL, DEPT_MNG и PRO_MNG определяются на ранее определенных доменах (определения доменов EMP_NO и SALARY приведены в предыдущей лекции). , DEPT и проектов являются столбцы EMP_NO, DEPT_NO и PRO_NO соответственно. В таблице столбцы DEPT_NO и PRO_NO являются внешними ключами, указывающими на отдел, в котором работает служащий, и на выполняемый им проект соответственно. В таблице DEPT DEPT_MNG, указывающий на служащего, являющегося руководителем соответствующего отдела, а в таблице PRO_MNG, указывающий на служащего, являющегося менеджером соответствующего проекта. Другие
Определим таблицу :
(1) CREATE TABLE EMP (
(2) EMP_NO EMP_NO PRIMARY KEY,
(3) EMP_NAME VARCHAR(20) DEFAULT 'Incognito' NOT NULL,
(4) EMP_BDATE DATE DEFAULT NULL CHECK (
VALUE >= DATE '1917-10-24'),
(5) EMP_SAL SALARY,
(6) DEPT_NO DEPT_NO DEFAULT NULL REFERENCES
DEPT ON DELETE SET NULL,
(7) PRO_NO PRO_NO DEFAULT NULL,
(8) FOREIGN KEY PRO_NO REFERENCES PRO (PRO_NO)
ON DELETE SET NULL,
(9) CONSTRAINT PRO_EMP_NO CHECK
((SELECT COUNT (*) FROM EMP E
WHERE E.PRO_NO = PRO_NO) <= 50));
Последовательно обсудим части этого определения. В части (1) указывается, что создается таблица с именем . В части (2) определяется столбец EMP_NO на домене EMP_NO. У этого столбца не определено AND к ограничениям, унаследованным столбцом от определения домена). Помимо прочего, это означает неявное указание запрета для данного столбца неопределенных значений. В части (3) определен столбец EMP_NAME на 'Incognito', и в качестве EMP_BDATE (дата рождения служащего). Он имеет тип данных DATE, NULL (даты рождения некоторых служащих неизвестны). Кроме того, ограничение столбца запрещает принимать на работу лиц, о которых известно, что они родились до Октябрьского переворота. В части (5) определен столбец EMP_SAL на домене SALARY. DEPT_NO определяется на одноименном домене (для наших целей его определение несущественно), но явно объявляется, что NULL (некоторые служащие не приписаны ни к какому отделу). Кроме того, добавляется DEPT_NO ссылается на первичный ключ таблицы DEPT. Определено DEPT во всех строках таблицы , ссылавшихся на эту строку, столбцу DEPT_NO должно быть присвоено неопределенное значение. В части (7) определяется столбец PRO_NO. Его определение аналогично DEPT_NO, но PRO_EMP_NO, которое требует, чтобы ни в одном проекте не участвовало больше 50 служащих (правила построения соответствующего
Определим таблицу DEPT:
(1) CREATE TABLE DEPT (
(2) DEPT_NO DEPT_NO PRIMARY KEY,
(3) DEPT_EMP_NO INTEGER NOT NULL CHECK (
VALUE BETWEEN 1 AND 100),
(4) DEPT_NAME VARCHAR(200) DEFAULT 'Nameless' NOT NULL,
(5) DEPT_TOTAL_SAL SALARY DEFAULT 1000000.00
NOT NULL CHECK (VALUE > = 100000.00),
(6) DEPT_MNG EMP_NO DEFAULT NULL
REFERENCES EMP ON DELETE SET NULL
CHECK (IF (VALUE IS NOT NULL) THEN
((SELECT COUNT(*) FROM DEPT
WHERE DEPT.DEPT_MNG = VALUE) = 1),
(7) CHECK (DEPT_EMP_NO =
(SELECT COUNT(*) FROM EMP
WHERE DEPT_NO = EMP.DEPT_NO)),
(8) CHECK (DEPT_TOTAL_SAL >=
(SELECT SUM(EMP_SAL) FROM EMP
WHERE DEPT_NO = EMP.DEPT_NO)));
Это определение мы обсудим в менее DEPT_MNG – часть (6). Этот столбец объявляется DEPT. Но мы хотим сказать больше. У отдела могут временно отсутствовать руководители, поэтому в столбце допускаются неопределенные значения. Но если у отдела имеется руководитель, то он должен являться руководителем только этого отдела. На первый взгляд можно было бы воспользоваться ограничением столбца . Но такое ограничение допускало бы наличие неопределенного столбца DEPT_MNG только в одной строке таблицы DEPT, а мы хотим допустить отсутствие руководителя у нескольких отделов. Поэтому потребовалось ввести более громоздкое
По поводу двух приведенных определений
На первый вопрос можно ответить следующим образом. Да, эти ограничения можно было бы включить в
Вот ответ на второй вопрос. Ограничение (9) в первом определении и ограничения (7) и (8) во втором определении внешне похожи, но сильно отличаются по своей сути. Ограничения (7) и (8) связаны с агрегатной семантикой столбцов DEPT_EMP_NO и DEPT_TOTAL_SAL таблицы DEPT. Отмена ограничений изменила бы смысл этих столбцов. Ограничение (9) является текущим административным ограничением. Если руководство предприятия примет решение разрешить использовать в одном проекте более 50 служащих, ограничение можно отменить без изменения смысла столбцов таблицы . Имея это в виду, мы ввели явное имя ограничения (9), чтобы при необходимости имелась простая возможность отменить это ограничение с помощью оператора .
Наконец, определим таблицу .
(1) CREATE TABLE PRO (
(2) PRO_NO PRO_NO PRIMARY KEY,
(3) PRO_TITLE VARCHAR(200)DEFAULT 'No title' NOT NULL,
(4) PRO_SDATE DATE DEFAULT CURRENT_DATE NOT NULL,
(5) PRO_DURAT INTERVAL YEAR DEFAULT INTERVAL '1'
YEAR NOT NULL,
(6) PRO_MNG EMP_NO UNIQUE NOT NULL
REFERENCES EMP ON DELETE NO ACTION,
(7) PRO_DESC CLOB(10M));
Столбец PRO_SDATE содержит дату начала проекта, а столбец PRO_DURAT – продолжительность проекта в годах. В этом определении имеет смысл прокомментировать часть (6). Мы считаем, что если отдел, по крайней мере временно, может существовать без руководителя, то у проекта всегда должен быть менеджер. Поэтому PRO_MNG является гораздо более строгим, чем DEPT_MNG в таблице DEPT. Сочетание ограничений и при отсутствии PRO_MNG. Другими словами, этот столбец обладает всеми характеристиками с соответствующим значением NO ACTION, запрещающим такие удаления. В совокупности это гарантирует, что у любого проекта будет существовать менеджер, являющийся служащим предприятия. В части (7) столбец PRO_DESC (описание проекта) определен как большой символьный объект с максимальным размером 10 Мбайт.
Оператор изменения определения имеет следующий синтаксис:
base_table_alteration ::= ALTER TABLE base_table_name
column_alteration_action
| base_table_constraint_alternation_action
Как видно из этого синтаксического правила, при выполнении одного оператора может быть выполнено либо действие по изменению
Действие по
column_alteration_action ::=
ADD [ COLUMN ] column_definition
| ALTER [ COLUMN ] column_name
{ SET default_definition | DROP DEFAULT }
| DROP [ COLUMN ] column_name
{ RESTRICT | CASCADE }
Итак, с использованием оператора можно добавлять к определению таблицы ADD ) и изменять или отменять и соответственно).
Смысл действия ADD COLUMN почти полностью совпадает со смыслом раздела . Указывается имя нового столбца, его тип данных или домен. Могут определяться ADD оператора , добавляется к уже существующей таблице, которая, скорее всего, содержит некоторый набор строк. В каждой из существующих строк новый столбец должен содержать некоторое значение, и считается, что сразу после выполнения действия ADD этим значением является ADD, обязательно должен иметь NULL ), но среди .
В действии можно изменить ( SET default_definition ) или отменить определение . Заметим, что изменение
Действие отменяет отвергается, если:
Если в действии присутствует спецификация , то его выполнение порождает неявное выполнение оператора для всех представлений и
Предположим, что на предприятии ввели систему премирования служащих. Каждый служащий может дополнительно к зарплате получать ежемесячную премию, не превышающую размер его зарплаты. Тогда разумно добавить к таблице новый столбец EMP_BONUS, используя оператор :
ALTER TABLE EMP ADD EMP_BONUS SALARY DEFAULT NULL CONSTRAINT BONSAL CHECK (VALUE < EMP_SAL);
Обратите внимание, что мы присвоили
При EMP_SAL таблицы для этого столбца явно не определялось
ALTER TABLE EMP ALTER EMP_SAL SET DEFAULT 15000.00.
При DEPT_TOTAL_SAL таблицы DEPT для него было установлено
ALTER TABLE DEPT ALTER DEPT_TOTAL_SAL DROP DEFAULT.
Обратите внимание, что после выполнения этого оператора при вставке новой строки в таблицу DEPT всегда потребуется явно указывать значение столбца DEPT_TOTAL_SAL. Хотя формально у столбца будет существовать SALARY (10000.00), оно не может быть занесено в таблицу DEPT, поскольку противоречит ограничению столбца DEPT_TOTAL_SAL CHECK (VALUE >= 100000.00).
Можно задуматься, действительно ли требуется поддерживать в таблице DEPT столбец DEPT_EMP_NO. Как мы видели, для его поддержки требуется проверять громоздкое ограничение целостности, а число служащих в любом отделе можно получить динамически с помощью простого запроса к таблице (собственно, этот запрос входит в ограничение целостности). Поэтому может оказаться разумным отменить DEPT_EMP_NO, выполнив следующий оператор :
ALTER TABLE DEPT DROP DEPT_EMP_NO CASCADE.
Напомним, что спецификация ведет к тому, что при выполнении оператора будет уничтожено не только DEPT_EMP_NO содержалась спецификация , поскольку это единственное внешнее определение ограничения является ограничением только столбца DEPT_EMP_NO.
Действие по
base_table_constraint_alternation_action ::=
ADD [ CONSTRAINT ] base_table_constraint_definition
| DROP CONSTRAINT constraint_name
{ RESTRICT | CASCADE }
Действие ADD [ позволяет добавить к набору существующих ограничений таблицы новое ограничение целостности. Можно считать, что новое ограничение добавляется через AND к . Но здесь имеется одно существенное отличие. Если внимательно посмотреть на все возможные виды табличных ограничений, можно убедиться, что любое из них удовлетворяется на пустой таблице. Поэтому, какой бы набор табличных ограничений ни был определен при . При добавлении нового табличного ограничения с использованием действия ADD [ мы имеем другую ситуацию, поскольку таблица, скорее всего, уже содержит некоторый набор строк, для которого false. В этом случае выполнение оператора , включающего действие ADD [ , отвергается.
Выполнение действия . действие отвергается, если на данный возможный ключ ссылается хотя бы один внешний ключ. При указании действие выполняется в любом случае, и все определения таких
Напомним, что мы добавили к таблице столбец EMP_BONUS, в котором сохраняются размеры ежемесячных премий служащих. Предположим, что премии выплачиваются из фонда DEPT_TOTAL_SAL, устанавливающее, что объем фонда зарплаты отдела не должен быть меньше суммарной зарплаты служащих этого отдела, становится недостаточным, и нам требуется добавить к набору ограничений таблицы DEPT новое ограничение:
ALTER TABLE DEPT ADD CONSTRAINT TOTAL_INCOME
CHECK (DEPT_TOTAL_SAL >=
(SELECT SUM(EMP_SAL + COALESCE(EMP_BONUS,0))
FROM EMP WHERE EMP.DEPT_NO = DEPT_NO)).
Хотя это ограничение на вид довольно сложное, смысл его очень прост: суммарный доход служащих отдела не должен превышать объем зарплаты отдела. В SUM используется операция COALESCE. Эта двуместная операция определяется следующим образом:
COALESCE (x, y) IF x IS NOT NULL THEN x ELSE y,
т. е. значением операции является значение первого операнда, если оно не равно NULL, и значение второго операнда – в противном случае. Нам пришлось воспользоваться этой операцией, поскольку в столбце EMP_BONUS допускается наличие неопределенных значений.
Понятно, что новое ограничение столбца DEPT_TOTAL_SAL сильнее предыдущего, и это предыдущее ограничение можно было бы отменить. Конечно, с логической точки зрения наличие обоих ограничений ничему не повредит (предыдущее ограничение является логическим следствием нового), но при использовании не слишком интеллектуальной реализации SQL может привести к замедлению работы системы, поскольку оба ограничения могут проверяться независимо. К сожалению, при определении таблицы мы не присвоили явное имя DEPT_TOTAL_SAL и поэтому не можем немедленно продемонстрировать оператор отмены этого ограничения. Это не значит, что его нельзя отменить вообще. В
Кстати, новому ограничению мы присвоили явное имя. К этому привели следующие рассуждения. Когда создавалась исходная
При определении таблицы было специфицировано PRO_EMP_NO, устанавливающее, что над одним проектом не должно работать более 50 служащих. Мы уже отмечали, что это ограничение носит чисто административный характер и может быть отменено без нарушения логики базы данных. Для отмены ограничения нужно выполнить следующий оператор:
ALTER TABLE EMP DROP CONSTRAINT PRO_EMP_NO;
Для отмены определения (уничтожения) , задаваемый в следующем синтаксисе:
DROP TABLE base_table_name { RESTRICT | CASCADE }
Успешное выполнение оператора приводит к тому, что указанная оператор выполняется в любом случае, и все определения представлений и
Виды
(рис 12.2) Иерархия видов ограничений целостностиНо иерархия видов , а мы их будем называть
Для определения , задаваемый в следующем синтаксисе:
CREATE ASSERTION constraint_name
CHECK (conditional_expression)
Заметим, что при создании
В определении таблицы содержалось ограничение столбца EMP_BDATE:
CHECK (EMP_BDATE >= '1917-10-24')
(к работе на предприятии допускаются только те лица, которые родились после Октябрьского переворота). Вот каким образом можно определить такое же ограничение на уровне
CREATE ASSERTION MIN_EMP_BDATE CHECK
(((SELECT MIN(EMP_BDATE)) FROM EMP) >= '1917-10-24')
В логическом условии этого общего ограничения выбирается минимальное значение столбца EMP_BDATE (дата рождения самого старого служащего). Значением false в том и только в том случае, если среди служащих имеется хотя бы один, родившийся до указанной даты.
Теперь переформулируем в виде , которое определялось следующим образом:
CONSTRAINT PRO_EMP_NO CHECK
((SELECT COUNT (*) FROM EMP E
WHERE E.PRO_NO = PRO_NO) <= 50)
(над одним проектом не может работать более 50 служащих).
Вот формулировка эквивалентного
CREATE ASSERTION NEW_PRO_EMP_NO CHECK
( NOT EXISTS (SELECT PRO_NO FROM EMP GROUP BY PRO_NO
HAVING COUNT(*) > 50)).
Логическое выражение этого ограничения может принимать только значения true и false. Внутренний оператор выборки группирует строки таблицы таким образом, что в одну группу попадают все строки с одинаковым значением столбца PRO_NO. Затем эти группы фильтруются по условию раздела HAVING, и остаются только группы, включающие более 50 строк. В результирующей таблице содержатся строки из одного столбца, содержащего значение PRO_NO оставшихся групп. Предикат NOT EXISTS принимает значение true тогда и только тогда, когда эта результирующая таблица не содержит ни одной строки, т. е. нет ни одного проекта, в котором работает больше 50 служащих.
Покажем, как можно сформулировать в виде PRO_NO, входящего в состав определения таблицы :
FOREIGN KEY PRO_NO REFERENCES PRO (PRO_NO)
В виде
(1) CREATE ASSERTION FK_PRO_NO CHECK
(2) ( NOT EXISTS (SELECT * FROM EMP
WHERE PRO_NO IS NOT NULL AND
(3) NOT EXISTS (SELECT * FROM PRO
(4) WHERE PRO.PRO_NO = EMP.PRO_NO))).
Логическое выражение этого ограничения выглядит достаточно сложным и нуждается в пояснении. Условие выборки оператора SELECT на строке (2) состоит из двух частей, связанных через AND. Первая часть отфильтровывает те строки таблицы , у которых в столбце PRO_NO содержится NULL. Если этот столбец содержит NULL во всех строках таблицы, то результирующая таблица оператора выборки на строке (2) будет пустой, и значением предиката NOT EXISTS будет true, т. е. ограничение удовлетворяется.
Теперь предположим, что в таблице cand_pro_no является допустимым значением
Если же найдется хотя бы одна строка таблицы с таким значением cand_pro_no столбца PRO_NO, что в таблице не найдется ни одной строки, значение столбца PRO_NO которой равнялось бы этому cand_pro_no, то результирующая таблица оператора выборки на строке (3) будет пустой, и значением предиката NOT EXISTS на строке (3) будет true. Тогда все условие выборки первого оператора SELECT примет значение true, и эта строка таблицы будет пропущена в результирующую таблицу. Значением предиката NOT EXISTS будет false, т. е. ограничение не удовлетворяется.
Мы сознательно привели такое подробное пояснение не только для того, чтобы прояснить смысл FK_PRO_NO, но и чтобы дать понять, во что реально вырождается простая синтаксическая конструкция определения
Наконец, сформулируем общее ограничение целостности, состоящее в том, что никакой
(1) CREATE ASSERTION PRO_MNG_CONSTR CHECK
(2) NOT EXISTS (SELECT * FROM EMP EMP1, EMP EMP2,
DEPT, PRO WHERE
(3) EMP1.EMP_NO = PRO.PRO_MNG AND
(4) EMP1.DEPT_NO = DEPT.DEPT_NO AND
(5) DEPT.DEPT_MNG = EMP2.EMP_NO AND
(6) EMP1.EMP_SAL + COALESCE (EMP1.EMP_BONUS,0) >
(7) EMP2.EMP_SAL + COALESCE (EMP2.EMP_BONUS,0);
В логическом выражении этого ограничения используется оператор выборки SELECT, в разделе перечня таблиц ( FROM ) впервые в этом курсе используется несколько таблиц. Такие запросы в SQL называются запросами с соединениями, и мы воспользуемся случаем, чтобы пояснить на примере (конечно, предварительно), как их следует понимать в соответствии со стандартом языка SQL.
Итак, в разделе FROM оператора выборки, используемого в логическом условии этого ограничения, через запятую перечислены четыре элемента – , , DEPT и . Выражение вида означает применение своего рода операции переименования. Внутри запроса столбцы этого "экземпляра" имеют "квалифицированные" имена вида ANOTHER_NAME.column_name, где column_name обозначает имя существующего столбца таблицы .
Вычисление оператора выборки начинается с того, что формируется расширенное
Условие раздела WHERE состоит из четырех частей, связанных через AND. Обсудим их последовательно. После проверки условия EMP1.EMP_NO = в таблице ALL_TOGETHER останутся все служащие-менеджеры проектов вместе со своими проектами в комбинации со всеми возможными отделами и всеми возможными служащими (назовем эту отфильтрованную таблицу ALL_TOGETHER_STEP1 ). После проверки условия EMP1.DEPT_NO = DEPT.DEPT_NO в таблице ALL_TOGETHER_STEP1 останутся все служащие-менеджеры проектов вместе со своими проектами и вместе с описанием своих отделов в комбинации со всеми возможными служащими (назовем эту отфильтрованную таблицу ALL_TOGETHER_STEP2 ). После проверки условия DEPT.DEPT_MNG = EMP2.EMP_NO в таблице ALL_TOGETHER_STEP2 останутся все служащие-менеджеры проектов вместе со своими проектами, вместе с описанием своих отделов и вместе с руководителями этих отделов (по одной строке для каждого допустимого сочетания " проект-менеджер_проекта-отдел_менеджера_проекта-руководитель_отдела_менеджера_проекта "). Назовем эту отфильтрованную таблицу ALL_TOGETHER_STEP3. Легко видеть, что после проверки условия EMP1.EMP_SAL + EMP1.EMP_BONUS > EMP2.EMP_SAL + EMP2.EMP_BONUS в таблице ALL_TOGETHER_STEP3 могут остаться только строки проект-менеджер_проекта-отдел_менеджера_проекта-руководитель_отдела_менеджера_проекта, в которых суммарный доход менеджера проекта превышает суммарный доход руководителя отдела, где работает NOT EXISTS будет false, и тем самым ограничение целостности PRO_MNG_CONSTR будет нарушено.
Для того чтобы отменить ранее определенное общее ограничение целостности, нужно воспользоваться оператором , задаваемым в следующем синтаксисе:
DROP ASSERTION constraint_name
Вот пример оператора, отменяющего определение дискриминационного PRO_MNG_CONSTR:
DROP ASSERTION PRO_MNG_CONSTR;
На первый взгляд кажется, что false при любой
CHECK (DEPT_EMP_NO =
(SELECT COUNT(*) FROM EMP
WHERE DEPT_NO = EMP.DEPT_NO))
из определения таблицы DEPT. Предположим, например, что в отдел зачисляется новый служащий. Тогда нужно выполнить две операции: (a) вставить новую строку в таблицу и (b) изменить соответствующую строку таблицы DEPT (прибавить единицу к значению столбца DEPT_EMP_NO ). Очевидно, что в каком бы порядке ни выполнялись эти операции, сразу после выполнения первой из них ограничение целостности будет нарушено, соответствующее действие будет отвергнуто, и мы никогда не сможем принять на работу нового служащего.
Поскольку
Для этого в качестве заключительной синтаксической конструкции к любому определению INITIALLY в следующей синтаксической форме:
INITIALLY { DEFERRED | IMMEDIATE }
[ [ NOT ] DEFERRABLE ]
Эта спецификация указывает, в каком режиме должно находиться данное ограничение целостности в начале выполнения любой транзакции ( и DEFFERABLE ). Если же возможный ключ используется в некотором определении NOT DEFFERABLE .
Комбинация INITIALLY DEFERRED NOT DEFERRABLE является недопустимой. Если в определении ограничения спецификация начального режима проверки отсутствует, то подразумевается наличие спецификации INITIALLY IMMEDIATE. При наличии явной или неявной спецификации INITIALLY IMMEDIATE и отсутствии явного указания возможности смены режима подразумевается наличие спецификации NOT DEFERRABLE. При наличии спецификации INITIALLY DEFERRED и отсутствии явного указания возможности смены режима подразумевается наличие спецификации DEFERRABLE.
При выполнении транзакции можно изменить режим проверки некоторых или всех , задаваемый в следующем синтаксисе:
SET CONSTRAINTS { constraint_name_commalist | ALL }
{ DEFERRED | IMMEDIATE }
Если в операторе указывается список имен DEFERRABLE ; если хотя бы для одного ограничения из списка это требование не выполняется, то операция отвергается. При указании ключевого слова ALL режим устанавливается для всех ограничений, в определении которых явно или неявно было указано DEFERRABLE. Если в качестве желаемого режима проверки ограничений задано DEFERRED, то все указанные ограничения переводятся в режим отложенной проверки. Если в качестве желаемого режима проверки ограничений задано IMMEDIATE, то все указанные ограничения переводятся в режим отвергается, и все указанные ограничения остаются в предыдущем режиме.
При выполнении операции COMMIT неявно выполняется операция SET CONSTRAINTS ALL IMMEDIATE. Если эта операция отвергается, то COMMIT срабатывает как ROLLBACK.
В этой и предыдущей лекциях мы обсудили наиболее важные аспекты языка SQL, связанные с определением схемы базы данных, – типы данных SQL, средства определения доменов,
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.