2008 г.
Базы данных. Вводный курс
Сергей Кузнецов
Назад Содержание Вперёд
15.3. Средства определения, изменения определения и отмены определения доменов
Как неоднократно упоминалось выше, при определении столбцов таблицы требуется явно указывать тип данных каждого столбца. Для этого можно использовать описанные выше средства спецификации типа. Но в SQL поддерживается и другой механизм— механизм доменов. Домен является долговременно хранимым, именованным объектом схемы базы данных. Домены можно создавать (определять), изменять (изменять определения) и ликвидировать (отменять определение). Имена доменов можно использовать при определении столбцов таблиц. Можно считать, что в SQL определение домена представляет собой вынесенное за пределы определения индивидуальной таблицы «родовое» определение столбца, которое можно использовать для определения различных реальных столбцов реальных базовых таблиц. В языке SQL обеспечиваются средства определения доменов, изменения и отмены существующих определений.
15.3.1. Определение домена
Для определения домена в SQL используется оператор CREATE DOMAIN
. Общий синтаксис этого оператора следующий:88)
domain_definition ::= CREATE DOMAIN domain_name [AS] data_type
[ default_definition ]
[ domain_constraint_definition_list ]
Здесь domain_name
задает имя создаваемого домена89), data_type
есть спецификация определяющего типа данных. В необязательных разделах default_definition
и domain_constraint_definition_list
специфицируются значение домена по умолчанию90) и набор ограничений целостности, которые будут применяться к любому столбцу, определенному на этом домене.
Раздел default_definition
имеет вид
DEFAULT { literal | niladic_function | NULL }
91)
Здесь literal
представляет любое допустимое литеральное значение определяющего типа домена, NULL
обозначает неопределенное значение, а niladic_function
может задаваться в одной из следующих форм:
USER
CURRENT_USER
SESSION_USER
SYSTEM_USER
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
92)
Если в операторе CREATE DOMAIN
значение по умолчанию не специфицируется, считается, что такого значения нет. Однако позже к определению домена можно добавить раздел значения по умолчанию с помощью оператора ALTER DOMAIN
. Кроме того, этот оператор позволяет удалить раздел значения по умолчанию из существующего определения домена.
Элемент списка domain_constraint_definition_list
имеет вид
[CONSTRAINT constraint_name]
CHECK (conditional_expression)
Необязательный раздел CONSTRAINT constraint_name
позволяет определить имя нового ограничения целостности. Если явное указание имени отсутствует, ограничению назначается имя, автоматически генерируемое системой. Что касается вида условного выражения, служащего собственно ограничением целостности, то в стандарте запрещается лишь прямое или косвенное использование в нем домена, в определение которого входит данное условное выражение.93) Однако наиболее естественным (и наиболее распространенным) видом ограничения домена является следующий:
CHECK (VALUE IN (list_of_valid_values))
Такое ограничение запрещает появление в любом столбце, определенном на данном домене, любого значения определяющего типа, не входящего в список допустимых значений.
15.3.2. Примеры определений доменов
В дальнейших примерах нам понадобятся определения нескольких доменов. Приведем их в этом подразделе. В примерах мы будем иметь дело с таблицами служащих (EMP
), отделов (DEPT
) и проектов (PRO
). Каждый служащий обладает уникальным номером (EMP_NO
) и получает заработную плату (SALARY
). Определим домены EMP_NO
и SALARY
.
CREATE DOMAIN EMP_NO AS INTEGER
CHECK (VALUE BETWEEN 1 AND 10000);
Номера служащих являются целыми числами, поэтому базовый тип домена EMP_NO
есть тип INTEGER
. Кроме того, на значения этого домена устанавливается следующее ограничение: они должны быть больше нуля и не превосходить целое значение 10000.
Домен SALARY
определим следующим образом:
CREATE DOMAIN SALARY AS NUMERIC (10, 2)
DEFAULT 10000.00
CHECK (VALUE BETWEEN 10000.00 AND 20000000.00)
CONSTRAINT SAL_NOT_NULL CHECK (VALUE IS NOT NULL);
Размер заработной платы является значением точного числового типа NUMERIC
из десяти десятичных цифр, две из которых составляют дробную часть. По умолчанию размер заработной платы составляет 10000 руб. Установлен диапазон допустимого размера зарплаты от 10000 руб. до 20000000 руб. Неопределенное значение зарплаты не допускается (на уровне определения домена).
15.3.3. Изменение определения домена
Для изменения характеристик ранее определенного домена используется оператор SQL ALTER DOMAIN
. Синтаксис этого оператора выглядит следующим образом:
domain_alternation ::=
ALTER DOMAIN domain_name domain_alternation_action
domain_alternation_action ::=
domain_default_alternation_action
| domain_constraint_alternation_action
Как видно из синтаксических правил, при изменении определения домена можно выполнить действие по изменению раздела значения по умолчанию либо изменить ограничение домена. Для первого варианта действует следующий синтаксис:
domain_default_alternation_action ::=
SET default_definition
| DROP DEFAULT
В случае установки нового значения по умолчанию (SET
) это значение автоматически применяется ко всем столбцам, определенным на данном домене. Более точно, это значение становится новым значением по умолчанию. Операция не оказывает влияния на состояние существующих строк таблиц базы данных. В случае отмены раздела значения по умолчанию в определении домена (DROP
) существовашее значение домена по умолчанию становится значением по умолчанию каждого столбца, который определен на данном домене и для которого не специфицировано собственное значение по умолчанию.
Действие по изменению ограничения домена определяется следующим синтаксисом:
domain_constraint_alternation_action ::=
ADD domain_constraint_definition
| DROP CONSTRAINT constraint_name
Действие по добавлению нового определения ограничения домена (ADD
) приводит к тому, что новое условие добавляется через AND
к существующему ограничению домена. Если к моменту выполнения соответствующего оператора ALTER DOMAIN
существуют столбцы некоторых таблиц, текущие значения которых противоречат новому ограничению, то СУБД должна отвергнуть этот оператор ALTER DOMAIN
. Действие по отмене ограничения домена (DROP
) приводит к исчезновению соответствующей части общего ограничения соответствующего домена, что, естественно, не влияет на существующие значения столбцов имеющихся таблиц.
15.3.4. Примеры изменения определения домена
Немного поупражняемся с доменом SALARY
. Для изменения значения заработной платы по умолчанию с 10000 на 11000 руб. нужно выполнить оператор
ALTER DOMAIN SALARY SET DEFAULT 11000.00;
Для отмены значения по умолчанию в домене SALARY
следует воспользоваться оператором
ALTER DOMAIN SALARY DROP DEFAULT;
Если к определению домена SALARY
требуется добавить ограничение (например, запретить значение зарплаты, равное 15000 руб.), необходимо выполнить оператор
ALTER DOMAIN SALARY ADD CHECK (VALUE <> 15000.00);
Наконец, если требуется отменить (именованное!) ограничение целостности, препятствующее наличию неопределенных значений в столбцах, которые определены на домене SALARY
, то нужно выполнить оператор
ALTER DOMAIN SALARY DROP CONSTRAINT SAL_NOT_NULL;
15.3.5. Отмена определения домена
Чтобы отменить ранее созданное определение домена, нужно воспользоваться оператором DROP DOMAIN
в следующем синтаксисе:
DROP DOMAIN domain_name {RESTRICT | CASCADES}
Если в операторе указано RESTRICT
, и если соответствующий домен использован в определении некоторого столбца, в определении некоторого представления или в определении ограничения целостности (см. следующие лекции), то оператор DROP DOMAIN
отвергается. В противном случае определение домена ликвидируется.
Если в операторе DROP DOMAIN
указано CASCADES
, то оператор выполняется всегда. При этом уничтожаются все представления и ограничения целостности, в определении которых использовалось имя данного домена. Столбцы, определенные на этом домене, автоматически переопределяются следующим образом:
- считается, что каждый такой столбец теперь относится к определяющему типу уничтожаемого домена;
- если у столбца не было определено собственное значение по умолчанию, то считается, что теперь у него имеется такое значение по умолчанию, совпадающее со значением по умолчанию уничтожаемого домена;
- каждый столбец наследует все ограничения уничтожаемого домена.
15.4. Неявные и явные преобразования типа или домена
В языке SQL обеспечивается возможность использования в различных операциях не только значений тех типов, для которых предопределена операция, но и значений типов, неявным или явным образом приводимых к требуемому типу.
15.4.1. Неявные преобразования типов в SQL
В SQL поддерживается совместимость некоторых типов данных за счет неявного преобразования значений одного типа к значениям другого типа данных (например, при необходимости FLOAT
неявно приводится к DOUBLE
). Опишем наиболее важные правила совместимости типов, принятые в SQL:1999. Начнем с определения приводимости типов. Тип данных A
приводим к типу данных B
в том и только в том случае, когда в любом месте, где ожидается значение типа B
, может быть использовано значение типа A
.
Основные правила приводимости типов состоят в следующем.
- Типы символьных строк. Тип
CHARACTER (x)
приводим к любому типу CHARACTER (y)
, если yx
. Типы VARCHAR (x)
и CHARACTER (x)
приводимы к любому типу VARCHAR (y)
, если yx
. Типы CHARACTER (x)
и VARCHAR (x)
приводимы к любому типу CLOB
. - Типы битовых строк. Тип
BIT (x)
приводим к любому типу BIT (y)
, если yx
. Типы BIT VARYING (x)
и BIT (x)
приводимы к любому типу BIT VARYING (y)
, если yx
. - Типы
BLOB
. Тип BLOB (x)
приводим к любому типу BLOB (y)
, если yx
. - Типы точных чисел. Тип
EN (p1, s1)
приводим к любому типу EN (p2, s2)
, у которого s2s1
и p2
определяется в реализации. Тип EN (p, s)
приводим к любому типу приблизительных чисел AN (p1)
, где p1
определяется в реализации. - Типы приблизительных чисел. Тип
AN (p1)
приводим к любому типу AN (p2)
, если p2p1
.
15.4.2. Явные преобразования типов или доменов и оператор CAST
Неявные преобразования типов не всегда удобны, недостаточно гибки и иногда могут вызывать ошибки. Поэтому, как показывает предыдущий подраздел, число допустимых неявных преобразований типов в SQL весьма ограничено. Однако в SQL существует специальный оператор CAST
, с помощью которого можно явно преобразовывать типы или домены в более широких пределах допускаемых преобразований. Конструкция имеет следующий синтаксис:
CAST ({scalar-expression | NULL } AS
{data_type | domain_name})
Оператор преобразует значение заданного скалярного выражения к указанному типу или к базовому типу указанного домена. Результатом применения оператора CAST
к неопределенному значению является неопределенное значение. Для значений, отличных от неопределенных, в стандарте приводятся подробные правила выполнения преобразований, которые интуитивно понятны.
Поясним действие оператора CAST
в наиболее важных случаях. Примем следующие обозначения типов данных:
EN
– точные числовые типы (Exact Numeric
)
AN
– приблизительные числовые типы (Approximate Numeric
)
C
– типы символьных строк (Character
)
FC
– типы символьных строк постоянной длины (Fixed-length Character
)
VC
– типы символьных строк переменной длины (Variable-length Character
)
B
– типы битовых строк (Bit String
)
FB
– типы битовых строк постоянной длины (Fixed-length Bit String
)
VB
– типы битовых строк переменной длины (Variable-length Bit String
)
D
– тип Date
T
– типы Time
TS
– типы Timestamp
YM
– типы Interval Year-Month
DT
– типы Interval Day-Time
Пусть TD
– это тип данных, к которому производится преобразование, а SD
– тип данных операнда. Тогда допустимы следующие комбинации («да» означает безусловную допустимость, «нет» – безусловную недопустимость и «?» – допустимость с оговорками).
SD | TD |
---|
| EN | AN | VC | FC | VB | FB | D | T | TS | YM | DT |
---|
EN | Да | Да | Да | Да | Нет | Нет | Нет | Нет | Нет | ? | ? |
---|
AN | Да | Да | Да | Да | Нет | Нет | Нет | Нет | Нет | Нет | Нет |
---|
C | Да | Да | ? | ? | Да | Да | Да | Да | Да | Да | Да |
---|
B | Нет | Нет | Да | Да | Да | Да | Нет | Нет | Нет | Нет | Нет |
---|
D | Нет | Нет | Да | Да | Нет | Нет | Да | Нет | Да | Нет | Нет |
---|
T | Нет | Нет | Да | Да | Нет | Нет | Нет | Да | Да | Нет | Нет |
---|
TS | Нет | Нет | Да | Да | Нет | Нет | Да | Да | Да | Нет | Нет |
---|
YM | ? | Нет | Да | Да | Нет | Нет | Нет | Нет | Нет | Да | Нет |
---|
DT | ? | Нет | Да | Да | Нет | Нет | Нет | Нет | Нет | Нет | Да |
---|
По поводу ячеек таблицы, содержащих знак вопроса, необходимо сделать несколько оговорок:
- если
TD
– интервал и SD
– тип точных чисел, то TD
должен содержать единственное поле даты-времени; - если
TD
– тип точных чисел и SD
– интервал, то SD
должен содержать единственное поле даты-времени; - если
SD
– тип символьных строк и TD
– тип символьных строк постоянной или переменной длины, то набор символов SD
и TD
должен быть одним и тем же.
15.5. Заключение
В этой лекции мы начали рассматривать средства языка SQL, позволяющие определять и динамически изменять схему базы данных. Наиболее важным для общего понимания языка является раздел 15.2. Типы данных SQL – система типов языка SQL (и любой SQL-ориентированной базы данных). В последних стандартах языка SQL поддерживаются:
- развитый набор предопределенных типов, включая ряд параметризованных типов;
- генераторы типов массивов и мультимножеств, элементами которых могут быть значения предопределенных типов, типов коллекций, анонимных строчных типов строк и типов, определенных пользователями;
- генератор анонимных строчных типов, в которых типом элемента строки может быть любой предопределенный тип, тип коллекции, анонимный строчный тип и тип, определенный пользователями;
- определяемый пользователем структурный тип, в котором типом элемента структуры может быть любой предопределенный тип, тип коллекции, анонимный строчный тип и тип, определенный пользователями; для определяемых пользователем структурных и индивидуальных типов можно определять пользовательские операции.
Нельзя с уверенностью сказать, что система типов языка SQL настолько полна, что может удовлетворить любые потребности, но можно отметить, что в этой системе типов отсутствует единый логический подход и имеется избыточность. Возможно, это станет понятнее после обсуждения в конце курса средств объектно-реляционных расширений языка SQL.
Как должно быть ясно из этой лекции, механизм доменов в SQL играет вспомогательную роль. Это не совсем те (может быть, и совсем не те) домены, поддержка которых предполагается реляционной моделью. Фактически определение домена обеспечивает спецификацию ограничений и значений по умолчанию, выносимых за пределы определения столбца. В комитете по стандартизации SQL обсуждается идея полного отказа от поддержки механизма доменов и замены его на соответствующим образом адаптированный механизм индивидуальных типов (см. последнюю лекцию курса).
88 Начиная с этого места мы будем приводить более или менее точный синтаксис конструкций языка SQL (не злоупотребляя излишествами). Без этого текст был бы менее точным и более объемным. Прописными буквами показываются «терминалы» – ключевые слова языка SQL.
89 Здесь мы в первый раз сталкиваемся с именем объекта базы данных. Не будем углублять ся в детали, но в общем случае имена объектов SQL-ориентированных баз данных имеют вид имя_каталога.имя_схемы.имя_объекта
. Этот подход к именованию объектов базы данных позволяет независимо создавать объекты в разных схемах, не заботясь о том, чтобы эти объекты имели разные простые имена. При использовании в операторе SQL простого имени объекта система должна автоматически уточнить это имя, исходя из идентификатора пользователя, от имени которого выполняется оператор.
90 Это значение будет использоваться в качестве значения по умолчанию для любого столбца, определенного на данном домене, для которого не определено собственное значение по умолчанию (см. следующую лекцию).
91 { element1, | element2, |…| elementn }
означает, что в данной синтаксической конструкции должен присутствовать один и только один elementi
.
92 Значение niladic_function
«вычисляется» в тот момент, когда требуется значение по умолчанию (обычно при вставке в таблицу новой строки, значение соответствующего столбца которой явно не указано). Смысл CURRENT_DATE
, CURRENT_TIME
и CURRENT_TIMESTAMP
очевиден. USER
(или, что то же, CURRENT USER
), SESSION_USER
и SYSTEM_USER
задают идентификатор пользователя, от имени которого выполняется текущая транзакция, текущая сессия, и идентификатор операционной системы, в которой работает пользователь, соответственно. В стандарте не определяется представление этих идентификаторов, но в реализациях они обычно представляются в виде символьных строк.
93 Более подробно мы обсудим допустимые в SQL виды условных выражений в следующих лекциях.
Назад Содержание Вперёд