CREATE DOMAIN

CREATE DOMAIN — define um novo domínio

Sinopse

CREATE DOMAIN nome_do_domínio [ AS ] tipo_de_dados
    [ COLLATE ordenação ]
    [ DEFAULT expressão ]
    [ restrição_de_domínio [ ... ] ]

onde restrição_de_domínio é:

[ CONSTRAINT nome_da_restrição ]
{ NOT NULL | NULL | CHECK (expressão) }

Descriçã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.

Parâmetros

nome_do_domínio

O nome (opcionalmente qualificado pelo esquema) do domínio a ser criado.

tipo_de_dados

O 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ção

Um nome opcional para a restrição. Se não for especificado, o sistema irá gerar um nome.

NOT NULL

Os valores desse domínio são impedidos de serem nulos (mas veja as notas abaixo).

NULL

Os 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.)

Notas

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.

Exemplos

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)


Conformidade

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).

Veja também

ALTER DOMAIN, DROP DOMAIN


[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.)