CREATE DOMAIN — создание нового домена
CREATE DOMAINname[ AS ]data_type[ COLLATEcollation] [ DEFAULTexpression] [domain_constraint[ ... ] ] гдеdomain_constraintимеет вид: [ CONSTRAINTconstraint_name] { NOT NULL | NULL | CHECK (expression) }
Команда CREATE DOMAIN создаёт новый домен. Домен, по сути, является типом данных с дополнительными ограничениями (ограничениями на допустимый набор значений). Пользователь, определяющий домен, становится его владельцем.
Если указано имя схемы (например, CREATE DOMAIN myschema.mydomain ...), то домен создаётся в указанной схеме. В противном случае он создаётся в текущей схеме. Имя домена должно быть уникальным среди типов и доменов, существующих в его схеме.
Домены полезны для вынесения общих ограничений на поля в одно место с целью упрощения поддержки. Например, несколько таблиц могут содержать столбцы адресов электронной почты, для всех которых требуется одинаковое ограничение CHECK для проверки синтаксиса адреса. Определить домен более удобно, чем настраивать ограничение для каждой таблицы отдельно.
Чтобы иметь возможность создать домен, вы должны иметь привилегию USAGE для базового типа.
nameИмя (возможно, с указанием схемы) создаваемого домена.
data_typeБазовый тип данных домена. Может включать спецификаторы массива.
collation
Необязательная сортировка для домена. Если сортировка не указана, домен имеет такое же поведение сортировки, как и его базовый тип данных. Базовый тип должен быть сортируемым, если указано COLLATE.
DEFAULT expression
Предложение DEFAULT задаёт значение по умолчанию для столбцов типа данных домена. Значение — это любое выражение без переменных (подзапросы не допускаются). Тип данных выражения по умолчанию должен соответствовать типу данных домена. Если значение по умолчанию не указано, то значением по умолчанию является NULL.
Выражение по умолчанию будет использоваться в любой операции вставки, которая не указывает значение для столбца. Если для конкретного столбца определён свой DEFAULT, он переопределяет значение по умолчанию, связанное с доменом. В свою очередь, значение по умолчанию домена переопределяет любое значение по умолчанию, связанное с базовым типом данных.
CONSTRAINT constraint_nameНеобязательное имя ограничения. Если не указано, система генерирует имя.
NOT NULLЗначения этого домена не могут быть равны NULL (но см. примечания ниже).
NULLЗначения этого домена могут быть равны NULL. Это поведение по умолчанию.
Это предложение предназначено только для совместимости с базами данных SQL, не соответствующими стандарту. Его использование в новых приложениях не рекомендуется.
CHECK (expression)
Предложения CHECK задают ограничения целостности или условия, которым должны удовлетворять значения домена. Каждое ограничение должно быть выражением, возвращающим логический результат. В нём следует использовать ключевое слово VALUE для ссылки на проверяемое значение. Выражения, результатом которых является TRUE или UNKNOWN, считаются успешными. Если выражение возвращает результат FALSE, сообщается об ошибке и значение не разрешается преобразовывать к типу домена.
В настоящее время выражения CHECK не могут содержать подзапросы или ссылаться на переменные, отличные от VALUE.
Если у домена несколько ограничений CHECK, они будут проверяться в алфавитном порядке по имени. (В версиях Digital Q.DataBase до 9.5 не соблюдался какой-либо определённый порядок срабатывания для ограничений CHECK.)
Ограничения домена, особенно NOT NULL, проверяются при преобразовании значения к типу домена. Возможна ситуация, когда столбец, номинально имеющий тип домена, может быть прочитан как NULL, несмотря на наличие такого ограничения. Например, это может произойти в запросе с внешним соединением, если столбец домена находится на стороне соединения, допускающей NULL. Более тонкий пример:
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
Пустой скалярный подзапрос выдаст значение NULL, которое считается имеющим тип домена, поэтому дальнейшая проверка ограничений к нему не применяется, и вставка будет успешной.
Избежать таких проблем очень сложно из-за общего предположения SQL о том, что значение NULL является допустимым значением для каждого типа данных. Поэтому лучшей практикой является проектирование ограничений домена таким образом, чтобы значение NULL было разрешено, а затем применять ограничения NOT NULL к столбцам типа домена по мере необходимости, а не непосредственно к типу домена.
Digital Q.DataBase предполагает, что условия ограничений CHECK являются неизменяемыми, то есть всегда дают одинаковый результат для одного и того же входного значения. Это предположение оправдывает проверку ограничений CHECK только при первом преобразовании значения к типу домена, а не в другие моменты. (Это, по сути, то же самое, что и обработка ограничений CHECK таблицы, описанная в Раздел 2.2.5.1.)
Типичный пример нарушения этого предположения — ссылка на пользовательскую функцию в выражении CHECK с последующим изменением поведения этой функции. Digital Q.DataBase не запрещает этого, но не заметит, если в хранимых значениях типа домена теперь нарушается ограничение CHECK. Это приведёт к сбою последующего дампа и восстановления базы данных. Рекомендуемый способ обработки такого изменения — удалить ограничение (с помощью ALTER DOMAIN), скорректировать определение функции и снова добавить ограничение, тем самым перепроверив его по отношению к хранимым данным.
Также хорошей практикой является обеспечение того, чтобы выражения CHECK домена не вызывали ошибок.
Этот пример создаёт тип данных us_postal_code, а затем использует этот тип в определении таблицы. Для проверки того, что значение похоже на действительный почтовый индекс США, используется регулярное выражение:
CREATE DOMAIN us_postal_code AS TEXT
CHECK(
VALUE ~ '^\d{5}$'
OR VALUE ~ '^\d{5}-\d{4}$'
);
CREATE TABLE us_snail_addy (
address_id SERIAL PRIMARY KEY,
street1 TEXT NOT NULL,
street2 TEXT,
street3 TEXT,
city TEXT NOT NULL,
postal us_postal_code NOT NULL
);
Команда CREATE DOMAIN соответствует стандарту SQL.
Синтаксис NOT NULL в этой команде является расширением Digital Q.DataBase. (Соответствующий стандарту способ записать то же самое — CHECK (VALUE IS NOT NULL). Однако, согласно «Примечания», такие ограничения всё равно лучше избегать на практике.) «Ограничение» NULL является расширением Digital Q.DataBase (см. также Compatibility).