CREATE DOMAIN

CREATE DOMAIN — определить новый домен

Синтаксис

CREATE DOMAIN имя [ AS ] тип_данных
    [ COLLATE правило_сортировки ]
    [ DEFAULT выражение ]
    [ ограничение [ ... ] ]

Где ограничение может быть:

[ CONSTRAINT имя_ограничения ]
{ NOT NULL | NULL | CHECK (выражение) }

Описание

Команда CREATE DOMAIN создает новый домен. Домен по существу является типом данных с дополнительными ограничениями (ограничениями на допустимый набор значений). Пользователь, определяющий домен, становится его владельцем.

Если задано имя схемы (например, CREATE DOMAIN myschema.mydomain ...), то домен создается в указанной схеме, в противном случае — в текущей. Имя домена должно быть уникальным среди имен типов и доменов, существующих в его схеме.

Домены полезны для реферирования общих характеристик разных полей в единое место для упрощения сопровождения. Например, несколько таблиц могут содержать столбцы адресов электронной почты, для проверки синтаксиса которых требуется одно и то же проверочное ограничение CHECK. Определите домен, вместо того чтобы устанавливать ограничение каждой таблицы по отдельности.

Чтобы иметь возможность создать домен, необходимо иметь право USAGE для нижележащего типа.

Параметры

имя

Имя создаваемого домена (может быть дополнено схемой).

тип_данных

Нижележащий тип данных домена. Может включать определение массива с этим типом.

правило_сортировки

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

DEFAULT выражение

Предложение DEFAULT задает значение по умолчанию для столбцов, типом данных которых является этот домен. Значением является любое выражение без переменной (но подзапросы не разрешены). Тип данных выражения по умолчанию должен соответствовать типу данных домена. Если значение по умолчанию не указано, оно равно NULL.

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

CONSTRAINT имя_ограничения

Необязательное имя ограничения. Если не указано, система создает имя.

NOT NULL

Значения этого домена не могут быть равны NULL (но см. Примечания ниже).

NULL

Значения этого домена могут быть равны NULL. Это значение по умолчанию.

Это предложение предназначено только для обеспечения совместимости с нестандартными базами данных SQL. В новых приложениях его использование не рекомендуется.

CHECK (выражение)

Предложения CHECK определяют ограничения целостности или проверки, которым должны удовлетворять значения домена. Каждое ограничение должно быть выражением, дающим логический результат. Проверяемое значение в этом выражении должно обозначаться ключевым словом VALUE. Выражения, выдающие значение TRUE или UNKNOWN, успешно выполняются. Если выражение выдает FALSE, появляется сообщение об ошибке и значение не может быть преобразовано в тип домена.

В настоящий момент выражения CHECK не могут содержать вложенные запросы и ссылаться на другие переменные, кроме VALUE.

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

Примечания

Ограничения домена, в частности, NOT NULL, проверяются при преобразовании значения в тип домена. Бывает, что даже несмотря на наличие такого ограничения, столбец, который номинально относится к типу домена, всё же можно прочитать как NULL. Например, это может произойти в запросе внешнего соединения, если столбец домена находится на стороне nullable внешнего соединения. Более тонкий пример:

INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));

Пустой скалярный SELECT создаст значение NULL, которое считается доменным типом, поэтому к нему не применяется дополнительная проверка ограничений, и добавление будет выполнена успешно.

Очень трудно избежать подобных проблем из-за общего предположения SQL, что значение NULL является допустимым значением каждого типа данных. Поэтому наилучшим решением будет разработать ограничения домена таким образом, чтобы разрешить значение NULL, а затем применить ограничения NOT NULL для столбцов типа домена по мере необходимости, а не непосредственно для типа домена.

QHB предполагает, что условия ограничений CHECK неизменны, то есть они всегда будут давать один и тот же результат для одного и того же входного значения. Именно это предположение объясняет проверку ограничений CHECK только при первом преобразовании значения в тип домена, а не при каждом обращении к нему. (По сути, таким же образом обрабатываются ограничения CHECK для таблиц, как описано в разделе Контрольные ограничения.)

Примером распространенного способа нарушения данного предположения является ссылка на определяемую пользователем функцию в ограничении CHECK, а затем изменение поведения этой функции. QHB не запрещает этого, но и не заметит, если есть сохраненные значения типа домена, которые теперь нарушают ограничение CHECK. Это может привести к сбою последующего дампа и перезагрузки базы данных. Рекомендуемый способ обработки такого изменения состоит в том, чтобы удалить ограничение (используя ALTER DOMAIN), настроить определение функции и повторно добавить ограничение, тем самым перепроверив его относительно сохраненных данных.

Примеры

В этом примере создается тип данных 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.

См. также

ALTER DOMAIN, DROP DOMAIN