CREATE DOMAIN — definir un nuevo dominio
CREATE DOMAINname[ AS ]data_type[ COLLATEcollation] [ DEFAULTexpression] [domain_constraint[ ... ] ] dondedomain_constraintes: [ CONSTRAINTconstraint_name] { NOT NULL | NULL | CHECK (expression) }
CREATE DOMAIN crea un nuevo dominio. Un dominio es esencialmente
un tipo de datos con restricciones opcionales (restricciones sobre el conjunto de
valores permitidos). El usuario que define un dominio se convierte en su propietario.
Si se proporciona un nombre de esquema (por ejemplo, CREATE DOMAIN
myschema.mydomain ...), el dominio se crea en el esquema especificado.
De lo contrario, se crea en el esquema actual. El nombre del dominio debe ser único
entre los tipos y dominios existentes en su esquema.
Los dominios son útiles para abstraer restricciones comunes en los campos en un solo lugar para facilitar su mantenimiento. Por ejemplo, varias tablas podrían contener columnas de dirección de correo electrónico, y todas requerirían la misma restricción CHECK para verificar la sintaxis de la dirección. Definir un dominio es preferible a configurar la restricción de cada tabla de forma individual.
Para poder crear un dominio, debes tener el privilegio USAGE
en el tipo subyacente.
nameEl nombre (opcionalmente calificado por esquema) del dominio que se va a crear.
data_typeEl tipo de datos subyacente del dominio. Puede incluir especificadores de matriz (array).
collation
Una colación (ordenación) opcional para el dominio. Si no se especifica ninguna colación,
el dominio tiene el mismo comportamiento de colación que su tipo de datos subyacente.
El tipo subyacente debe ser colacionable si se especifica COLLATE.
DEFAULT expression
La cláusula DEFAULT especifica un valor por defecto para las columnas
del tipo de datos del dominio. El valor es cualquier expresión libre de variables (pero no
se permiten subconsultas). El tipo de datos de la expresión por defecto debe coincidir con
el tipo de datos del dominio. Si no se especifica ningún valor por defecto, entonces el
valor por defecto es el valor nulo (null).
La expresión por defecto se utilizará en cualquier operación de inserción que no especifique un valor para la columna. Si se define un valor por defecto para una columna particular, anula cualquier valor por defecto asociado con el dominio. A su vez, el valor por defecto del dominio anula cualquier valor por defecto asociado con el tipo de datos subyacente.
CONSTRAINT constraint_nameUn nombre opcional para una restricción. Si no se especifica, el sistema genera un nombre.
NOT NULLEvita que los valores de este dominio sean nulos (pero consulta las notas a continuación).
NULLPermite que los valores de este dominio sean nulos. Este es el valor por defecto.
Esta cláusula solo está pensada para la compatibilidad con bases de datos SQL no estándar. Se desaconseja su uso en aplicaciones nuevas.
CHECK (expression)
Las cláusulas CHECK especifican restricciones de integridad o pruebas que
los valores del dominio deben cumplir. Cada restricción debe ser una expresión que produzca
un resultado booleano. Debe usar la palabra clave VALUE para referirse al
valor que se está probando. Las expresiones que se evalúan como TRUE o UNKNOWN tienen éxito.
Si la expresión produce un resultado FALSE, se informa de un error y no se permite que el valor
se convierta al tipo de dominio.
Actualmente, las expresiones CHECK no pueden contener subconsultas ni hacer
referencia a variables que no sean VALUE.
Cuando un dominio tiene múltiples restricciones CHECK, se probarán en orden
alfabético por su nombre. (Las versiones de PostgreSQL anteriores a
la 9.5 no respetaban ningún orden de disparo particular para las restricciones CHECK).
Las restricciones de dominio, particularmente NOT NULL, se comprueban al
convertir un valor al tipo de dominio. Es posible que una columna que es nominalmente del tipo
de dominio se lea como nula a pesar de existir tal restricción. Por ejemplo, esto puede suceder
en una consulta de combinación externa (outer join), si la columna del dominio está en el lado
anulable de la combinación externa. Un ejemplo más sutil es:
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
La subconsulta SELECT escalar vacía producirá un valor nulo que se considera que es del tipo de dominio, por lo que no se aplica ninguna otra comprobación de restricciones sobre él, y la inserción tendrá éxito.
Es muy difícil evitar este tipo de problemas debido a la suposición general de SQL de que un
valor nulo es un valor válido para cada tipo de datos. Por lo tanto, la mejor práctica es diseñar
las restricciones de un dominio de manera que se permita un valor nulo, y luego aplicar restricciones
NOT NULL a las columnas del tipo de dominio según sea necesario, en lugar de aplicarlas
directamente al tipo de dominio.
PostgreSQL asume que las condiciones de las restricciones CHECK
son inmutables, es decir, que siempre darán el mismo resultado para el mismo valor de entrada. Esta
suposición es lo que justifica examinar las restricciones CHECK únicamente cuando
un valor se convierte por primera vez a un tipo de dominio, y no en otros momentos. (Esto es esencialmente
lo mismo que el tratamiento de las restricciones CHECK de tabla, como se describe en
la Section 5.5.1).
Un ejemplo de una forma común de romper esta suposición es hacer referencia a una función definida
por el usuario en una expresión CHECK, y luego cambiar el comportamiento de esa
función. PostgreSQL no lo prohíbe, pero no notará si hay valores almacenados
del tipo de dominio que ahora violan la restricción CHECK. Eso causaría que un volcado y
restauración posterior de la base de datos falle. La forma recomendada de manejar tal cambio es eliminar
la restricción (usando ALTER DOMAIN), ajustar la definición de la función y volver
a añadir la restricción, volviendo a comprobarla contra los datos almacenados.
También es una buena práctica asegurarse de que las expresiones CHECK del dominio
no lancen errores.
Este ejemplo crea el tipo de datos us_postal_code y luego utiliza el tipo en la definición
de una tabla. Se utiliza una prueba de expresión regular para verificar que el valor parece un código postal
válido de los EE. UU.:
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
);
El comando CREATE DOMAIN cumple con el estándar SQL.
La sintaxis NOT NULL en este comando es una extensión de PostgreSQL.
(Una forma que cumple con el estándar para escribir lo mismo para tipos de datos no compuestos sería
CHECK (VALUE IS NOT NULL). Sin embargo, según las the section called “Notas”,
estas restricciones es mejor evitarlas en la práctica de todos modos). La «restricción» NULL
es una extensión de PostgreSQL (consulta también la
Compatibilidad).