CREATE DOMAIN — define um novo domínio
CREATE DOMAINnome_do_domínio[ AS ]tipo_de_dados[ COLLATEordenação] [ DEFAULTexpressão] [restrição_de_domínio[ ... ] ] onderestrição_de_domínioé: [ CONSTRAINTnome_da_restrição] { NOT NULL | NULL | CHECK (expressão) }
O comando CREATE DOMAIN define um novo domínio.
Um domínio é essencialmente um tipo de dados com restrições opcionais
(restrições sobre o conjunto de valores permitidos).
O usuário que define o domínio torna-se seu dono
[120]
[121].
Se for especificado um nome de esquema (por exemplo,
CREATE DOMAIN meu_esquema.meu_domínio ...),
então o domínio será criado no esquema especificado.
Caso contrário, será criado no esquema corrente.
O nome do domínio deve ser único entre os tipos de dados e domínios
existentes no esquema.
Os domínios são úteis para abstrair restrições comuns em campos em
um único local para manutenção.
Por exemplo, várias tabelas podem conter coluna de endereço de
correio eletrônico, todas exigindo a mesma verificação de restrição
(CHECK) para validar a sintaxe do endereço.
Neste caso, definir um domínio é mais prático do que configurar a
restrição de verificação em cada tabela individualmente.
Para poder criar um domínio, é necessário ter o privilégio
USAGE no tipo de dados subjacente.
nome_do_domínioO nome (opcionalmente qualificado pelo esquema) do domínio a ser criado.
tipo_de_dadosO tipo de dados subjacente do domínio. Pode incluir especificadores de matriz.
ordenação
Uma ordenação opcional para o domínio.
Se não for especificada nenhuma ordenação, o domínio terá o
mesmo comportamento de ordenação que seu tipo de dados subjacente.
O tipo de dados subjacente deve possuir ordenação se for
especificado COLLATE.
DEFAULT expressão
A cláusula DEFAULT especifica o valor padrão
para as colunas do tipo de dados do domínio.
O valor é qualquer expressão livre de variável
(mas subconsultas não são permitidas).
O tipo de dados da expressão do valor padrão deve corresponder
ao tipo de dados do domínio.
Se não for especificado nenhum valor padrão, o valor padrão
será o valor nulo.
A expressão do valor padrão será usada em qualquer operação de inserção que não especifique um valor para a coluna. Se for definido o valor padrão para uma determinada coluna, ele irá prevalecer sobre qualquer valor padrão associado ao domínio. Por sua vez, o valor padrão do domínio prevalece sobre qualquer valor padrão associado ao tipo de dados subjacente.
CONSTRAINT nome_da_restriçãoUm nome opcional para a restrição. Se não for especificado, o sistema irá gerar um nome.
NOT NULLOs valores desse domínio são impedidos de serem nulos (mas veja as notas abaixo).
NULLOs valores desse domínio podem ser nulos. Este é o comportamento padrão.
Esta cláusula destina-se apenas à compatibilidade com bancos de dados SQL fora do padrão. Seu uso é desencorajado em novas aplicações.
CHECK (expressão)
As cláusulas CHECK especificam restrições de
integridade, ou testes, que os valores do domínio devem satisfazer.
Cada restrição deve ser uma expressão produzindo um resultado booleano.
Deve ser usada a palavra-chave VALOR para se
referir ao valor que está sendo testado.
Expressões avaliadas como TRUE ou
UNKNOWN são bem-sucedidas.
Se a expressão produzir um resultado FALSE,
será relatado erro e o valor não poderá ser convertido para o
tipo de dados do domínio.
No momento, as expressões CHECK não podem
conter subconsultas, nem se referir a variáveis diferentes de
VALUE.
Quando um domínio possui várias restrições CHECK,
elas são testadas em ordem alfabética por nome.
(As versões do PostgreSQL anteriores
a 9.5 não obedeciam a nenhuma ordem de disparo específica para as
restrições CHECK.)
As restrições de domínio, particularmente NOT NULL,
são verificadas ao converter um valor para o tipo de dados do domínio.
É possível para uma coluna, que é nominalmente do tipo de dados do
domínio, ser lida como nula, apesar de haver esta restrição.
Por exemplo, isto pode acontecer em uma consulta de junção externa,
se a coluna do domínio estiver no lado anulável da junção externa.
Um exemplo mais sutil é
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
O sub-SELECT escalar vazio irá produzir um valor nulo considerado do tipo de dados do domínio, portanto, nenhuma verificação adicional de restrição será aplicada a ele, e a inserção será bem-sucedida.
É muito difícil evitar estes problemas, devido à suposição geral do
padrão SQL de que o valor nulo é um valor válido
para todos os tipos de dados.
A melhor prática, portanto, é especificar as restrições do domínio
de forma que o valor nulo seja permitido e, em seguida, aplicar as
restrições de coluna NOT NULL às colunas do
tipo de dados do domínio conforme necessário, em vez de diretamente
ao tipo de dados do domínio.
O PostgreSQL assume que as condições das
restrições CHECK são imutáveis, ou seja, sempre
dão o mesmo resultado para o mesmo valor de entrada.
Esta suposição é o que justifica examinar as restrições
CHECK somente quando o valor é convertido pela
primeira vez para ser do tipo de dados do domínio, e não em outros
momentos.
(Isto é essencialmente o mesmo que o tratamento das restrições
CHECK de tabela, conforme descrito na
Restrições de verificação.)
Um exemplo de maneira comum de quebrar esta suposição é fazer
referência a uma função definida pelo usuário em uma expressão
CHECK e, em seguida, alterar o comportamento
dessa função.
O PostgreSQL não proíbe isto, mas não irá
notar se houver valores armazenados do tipo de dados do domínio
que agora violam a restrição CHECK.
Isto faz com que um salvamento do banco de dados e posterior
recuperação falhem.
A maneira recomendada de lidar com este problema é remover a restrição
(usando o comando ALTER DOMAIN), ajustar a definição
da função, e adicionar novamente a restrição, verificando-a novamente
em relação aos dados armazenados.
Também é uma boa prática garantir que as expressões de domínio
CHECK não gerem erros.
Este exemplo cria o tipo de dados us_postal_code,
e usa o tipo de dados em uma definição de tabela.
Um teste de expressão regular é usado para verificar se o valor
se parece com um código postal válido dos EUA:
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
);
Exemplo 78. Exemplo do tradutor
Códigos postais de Petrópolis, RJ
Os códigos postais (CEPs) de Petrópolis, RJ, variam de acordo com a rua e o bairro, geralmente situando-se na faixa de 25600-000 a 25799-999.
CREATE DOMAIN cep_petropolis AS text
CHECK(
VALUE ~ '^\d{5}-\d{3}$' AND
VALUE >= '25600-000' AND
VALUE <= '25799-999'
);
CREATE DOMAIN
CREATE TABLE tbl_cep_petropolis (
cep cep_petropolis PRIMARY KEY,
logradouro text
);
CREATE TABLE
INSERT INTO tbl_cep_petropolis VALUES ('25610-000', 'Rua Epitácio Pessoa');
INSERT INTO tbl_cep_petropolis VALUES ('25620-000', 'Rua do Imperador');
INSERT INTO tbl_cep_petropolis VALUES ('22260-050', 'Rua Alzira Cortes');
ERRO: o valor para o domínio cep_petropolis viola a
restrição de verificação "cep_petropolis_check"
INSERT INTO tbl_cep_petropolis VALUES ('25600', 'Petrópolis');
ERRO: o valor para o domínio cep_petropolis viola a
restrição de verificação "cep_petropolis_check"
SELECT * FROM tbl_cep_petropolis;
cep | logradouro
-----------+---------------------
25610-000 | Rua Epitácio Pessoa
25620-000 | Rua do Imperador
(2 linhas)
O comando CREATE DOMAIN está em conformidade com
o padrão SQL.
A sintaxe contendo NOT NULL neste comando é uma
extensão do PostgreSQL.
(Uma forma de escrever o mesmo para tipos de dados não compostos,
em conformidade com o padrão, seria
CHECK (VALUE IS NOT NULL).
Entretanto, conforme indicado nas
Notas, é melhor evitar estas
restrições na prática.)
A “restrição” NULL é uma extensão do
PostgreSQL
(veja também Conformidade).
[120] Um domínio é um conjunto de valores permitidos. Um domínio é definido em um esquema e identificado por um <nome do domínio>. O objetivo de um domínio é restringir o conjunto de valores válidos que podem ser armazenados em uma coluna de uma tabela base por várias operações. Uma definição de domínio especifica um tipo de dados. Também pode especificar uma <restrição de domínio>, que restringe ainda mais os valores válidos do domínio, e uma <cláusula padrão>, que especifica o valor a ser usado na ausência de um valor explicitamente especificado, ou padrão da coluna. ISO/IEC 9075-2:1999 (E) – 4.14 Domains (N. T.)
[121] Uma restrição de domínio é uma restrição especificada para um domínio. Ela é aplicado a todas as colunas baseadas neste domínio, e a todos os valores convertidos para este domínio. ISO/IEC 9075-2:1999 (E) – 4.17.3 Domain constraints (N. T.)