# Cláusula CONSTRAINT

A cláusula CONSTRAINT é uma parte opcional da Instrução CREATE TABLE e da Instrução ALTER TABLE. A restrição é uma regra com a qual os dados devem estar em conformidade. O nome da restrição é opcional.

A restrição pode ser:

- restrição no nível-de-coluna

  As restrições no nível-de-coluna fazem referência a uma única coluna da tabela, e não especificam o nome da coluna (exceto as restrições de verificação). Se referem à coluna a qual seguem.

- restrição no nível-de-tabela

  As restrições no nível-de-tabela fazem referência a uma ou mais colunas da tabela. As restrições no nível-de-tabela especificam os nomes das colunas às quais se aplicam. As restrições de verificação (CHECK) no nível de tabela podem fazer referência a zero ou mais colunas da tabela.

As restrições de coluna incluem:

- NOT NULL

  Especifica que a coluna não pode conter valores nulos (não pode ser dado nome a restrições deste tipo).

- PRIMARY KEY

  Especifica a coluna que identifica unicamente uma linha da tabela. A coluna identificada deve ser definida como NOT NULL.

  Nota: Se for tentado adicionar uma chave primária utilizando a instrução ALTER TABLE, e alguma coluna incluída na chave primária contiver valores nulos, será gerado um erro e a chave primária não será adicionada. Para obter mais informações deve ser consultada a Instrução ALTER TABLE.
- UNIQUE

  Especifica que os valores na coluna devem ser únicos. Não são permitidos valores nulos.

- FOREIGN KEY

  Especifica que os valores na coluna devem corresponder a valores em uma coluna de chave primária ou de chave única referenciada, ou que são nulos.

- CHECK

  Especifica regras para os valores da coluna.

As restrições de tabela incluem:

- PRIMARY KEY

  Especifica a coluna ou colunas que identificam unicamente uma linha da tabela. Não são permitidos valores nulos.

- UNIQUE

  Especifica que os valores nas colunas devem ser únicos. As colunas identificadas devem ser definidas como NOT NULL.

- FOREIGN KEY

  Especifica que os valores nas colunas devem corresponder a valores em colunas de uma chave primária ou chave única referenciada, ou que são nulos.

  Nota: Se a chave estrangeira for formada por várias colunas, e se alguma coluna for nula, toda a chave será considerada nula. A inserção será permitida não importando o que esteja presente nas colunas não-nulas.
- CHECK

  Especifica diversas regras para os valores na tabela.

As restrições de coluna e restrições de tabela possuem a mesma função; a diferença é onde são especificadas. As restrições de tabela permitem especificar mais de uma coluna na definição da restrição PRIMARY KEY, UNIQUE, CHECK e FOREIGN KEY. As restrições no nível-de-coluna (exceto as restrições de verificação) fazem referência a apenas uma coluna.

#### Sintaxe

#### Restrições de chave primária e de unicidade

A chave primária define o conjunto de colunas que identificam unicamente as linhas da tabela.

Quando se cria uma restrição de chave primária, nenhuma das colunas incluídas na chave primária pode ter a restrição NULL; ou seja, não podem permitir valores nulos.

A instrução ALTER TABLE ADD PRIMARY KEY permite incluir colunas existentes em uma chave primária, caso estas tenham sido anteriormente definidas como NOT NULL. Os valores NULL não são permitidos. Se as colunas contiverem valores nulos, o sistema não adicionará a restrição de chave primária. Para obter mais informações deve ser consultada a Instrução ALTER TABLE.

A tabela pode ter no máximo uma restrição PRIMARY KEY, mas pode ter várias restrições UNIQUE.

#### Restrições de chave estrangeira

As chaves estrangeiras fornecem um meio de impor a integridade referencial de um banco de dados. A chave estrangeira é uma coluna, ou grupo de colunas, dentro da tabela que fazem referência a uma chave de alguma outra tabela (ou algumas vezes, embora raramente, à mesma tabela). A chave estrangeira deve incluir sempre colunas cujos tipos correspondem exatamente aos tipos das colunas da restrição de chave primária ou de unicidade referenciada.

Em uma restrição de chave estrangeira no nível-de-tabela, para a qual são especificadas as colunas da tabela que compõem a restrição, a mesma coluna não pode ser usada mais de uma vez.

Se houver uma lista de colunas na EspecificaçãoReferencias (lista das colunas na tabela referenciada), esta lista deverá corresponder a uma restrição de chave primária ou a uma restrição de unicidade da tabela referenciada. A EspecificaçãoReferencias pode omitir a lista de colunas da tabela referenciada, se esta tabela possuir uma chave primária declarada.

Se não houver uma lista de colunas na EspecificaçãoReferencias, e a tabela referenciada não possuir uma chave primária, será lançada uma exceção de instrução (Isto significa que se a tabela referenciada possuir apenas chaves únicas, é necessário incluir a lista de colunas na EspecificaçãoReferencias).

A restrição de chave estrangeira está satisfeita quando há um valor correspondente na coluna de unicidade ou de chave primária correspondente. Se a chave estrangeira for composta por várias colunas, o valor da chave estrangeira será considerado nulo quando qualquer uma de suas colunas tiver o valor nulo.
Nota: É possível que uma chave estrangeira formada por várias colunas permita que uma de suas colunas contenha um valor para o qual não exista valor correspondente nas colunas referenciadas, de acordo com o padrão SQL-92. Para evitar esta situação, devem ser criadas restrições NOT NULL em todas as colunas da chave estrangeira.

#### Restrições de chave estrangeira e a DML

Quando é feita uma inserção ou atualização em uma tabela que possui uma restrição de chave estrangeira habilitada, o Derby verifica se a linha não viola a restrição de chave estrangeira procurando a chave referenciada correspondente na tabela referenciada. Se a restrição não for satisfeita, o Derby rejeitará a inserção ou a atualização através de uma exceção de instrução.

Quando uma linha de uma tabela com uma chave referenciada (uma restrição de chave primária ou de unicidade referenciada por uma chave estrangeira) é atualizada ou removida, o Derby verifica todas as restrições de chave estrangeira que fazem referência à chave, para ter certeza que a remoção ou a modificação da linha não causa violação da restrição. Se a remoção ou a modificação da linha causar uma violação da restrição, a atualização ou remoção não será permitida, e o Derby lançará uma exceção de instrução.

O Derby realiza as verificações de restrição no momento em que a instrução é executada, e não quando a transação é efetivada.

#### Índices de apoio

As restrições UNIQUE, PRIMARY KEY e FOREIGN KEY geram índices que impõem, ou "apoiam", à restrição (sendo algumas vezes chamados de índices de apoio). As restrições UNIQUE e PRIMARY KEY geram índices únicos. As restrições FOREIGN KEY geram índices que não são únicos. Portanto, se uma coluna, ou conjunto de colunas, estiverem envolvidas em uma restrição UNIQUE, PRIMARY KEY ou FOREIGN KEY, não é necessário criar índices nestas colunas para melhorar o desempenho, o Derby já terá criado o índice. Consulte Índices e restrições.

Estes índices ficam disponíveis para o otimizador para a otimização de comandos (consulte a Instrução CREATE INDEX), e possuem nomes gerados pelo sistema.

Não é permitido remover um índice de apoio através da instrução DROP INDEX; é necessário remover a restrição ou a tabela.

#### Restrições de verificação

As restrições de verificação podem ser utilizadas para especificar diversas regras para o conteúdo da tabela. É especificada uma condição de procura (que é uma expressão booleana), para a restrição de verificação. Esta condição de procura deve ser satisfeita por todas as linhas da tabela. A condição de procura é aplicada a toda linha modificada por uma instrução INSERT ou UPDATE, na hora em que a linha é modificada. A instrução é interrompida por completo quando qualquer restrição de verificação é violada.

#### Requisitos da condição de procura

Se a restrição de verificação for especificada como parte da definição-da-coluna, a referência a coluna somente poderá ser feita para a mesma coluna. As restrições de verificação especificadas como parte da definição da tabela, podem possuir referência a colunas que identificam colunas definidas anteriormente na instrução CREATE TABLE.

A condição de procura deve retornar sempre o mesmo valor quando for aplicada aos mesmos valores. Portanto, não pode conter:

- Parâmetros dinâmicos (?)
- Funções de Data/Hora (CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP)
- Subconsultas
- Funções de usuário (tal como USER, SESSION_USER, CURRENT_USER)

#### Ações referenciais

Quando a chave estrangeira é definida, pode ser especificada uma cláusula ON DELETE e/ou ON UPDATE seguida pela ação apropriada (CASCADE, RESTRICT, SET NULL ou NO ACTION). Estas cláusulas especificam se o Derby deve modificar os valores da chave estrangeira correspondente ou não permitir a operação, para manter o relacionamento de chave estrangeira intacto quando o valor da chave primária for atualizado ou excluído da tabela.

A regra de atualização ou de exclusão da restrição referencial é especificada quando a restrição referencial é definida.

A regra de atualização é aplicada quando uma linha da tabela mãe ou da tabela dependente é atualizada. As escolhas são NO ACTION e RESTRICT.

Quando se atualiza o valor de uma coluna da chave primária da tabela mãe, e a regra de atualização está especificada como RESTRICT, o Derby verifica as tabelas dependentes com relação às restrições de chave estrangeira. Se alguma linha de tabela dependente violar a restrição de chave estrangeira, a transação será desfeita.

Se a regra de atualização for NO ACTION, o Derby verificará as tabelas dependentes com relação às restrições de chave estrangeira após todas as exclusões terem sido executadas, mas antes dos gatilhos serem executados. Se alguma linha de tabela dependente violar a restrição de chave estrangeira, a instrução será rejeitada.

Quando é atualizado o valor de uma coluna em uma tabela dependente, e este valor faz parte da chave estrangeira, a regra de atualização implícita é NO ACTION. NO ACTION significa que se a chave estrangeira for atualizada com um valor não-nulo, o valor atualizado deverá corresponder a um valor na chave primária da tabela mãe quando a instrução estiver completa. Se a atualização não corresponder a um valor na chave primária da tabela mãe, a instrução será rejeitada.

A regra de exclusão é aplicada quando uma linha da tabela mãe é excluída, e esta linha possui dependentes na tabela dependente da restrição referencial. Quando são excluídas linhas da tabela dependente, a operação de exclusão da tabela mãe é dita como propagada para a tabela dependente. Se a tabela dependente também for uma tabela mãe, a ação especificada será aplicada, por sua vez, às suas tabelas dependentes.

As escolhas são NO ACTION, RESTRICT, CASCADE e SET NULL. SET NULL somente poderá ser especificada quando alguma coluna da chave estrangeira permitir valores nulos.

Se a regra de exclusão for:

NO ACTION, o Derby verificará as tabelas dependentes com relação às restrições referenciais após todas as exclusões terem sido executadas, mas antes dos gatilhos serem executados. Se alguma linha da tabela dependente violar a restrição de chave estrangeira, a instrução será rejeitada.

RESTRICT, o Derby verificará as tabelas dependentes com relação às chaves estrangeiras. Se alguma linha da tabela dependente violar a restrição de chave estrangeira, a transação será desfeita.

CASCADE, a operação de exclusão será propagada para a tabela dependente (e para as dependentes desta tabela, caso se aplique).

SET NULL, todas as colunas da chave estrangeira da tabela dependente que aceitam o valor nulo, receberão o valor nulo (Novamente, se a tabela dependente também possuir tabelas dependentes, as colunas das chaves estrangeiras destas tabelas que aceitam o valor nulo, receberão o valor nulo)

Cada restrição referencial onde a tabela é a tabela mãe, possui suas próprias regras de exclusão; todas as regras de exclusão aplicáveis são utilizadas para determinar o resultado da operação de exclusão. Portanto, não poderá ser excluída uma linha que possua dependentes em uma restrição referencial com regra de exclusão RESTRICT ou NO ACTION. De forma semelhante, a linha não poderá ser excluída quando a exclusão se propagar em cascata para alguma de suas descendentes que seja dependente em uma restrição referencial com a regra de exclusão RESTRICT ou NO ACTION.

A exclusão de uma linha da tabela mãe envolve outras tabelas. Qualquer tabela envolvida em uma operação de exclusão na tabela mãe é dita como sendo conectada-para-exclusão com a tabela mãe. A exclusão pode afetar as linhas destas tabelas das seguintes maneiras:

- Se a regra de exclusão for RESTRICT ou NO ACTION, a tabela dependente estará envolvida na operação, mas não será afetada pela operação (ou seja, o Derby verificará os valores na tabela, mas não excluirá qualquer valor).
- Se a regra de exclusão for SET NULL, as linhas da tabela dependente poderão ser atualizadas quando uma linha da tabela mãe for objeto de uma exclusão ou de uma operação de exclusão propagada.
- Se a regra de exclusão for CASCADE, as linhas da tabela dependente poderão ser excluídas quando a tabela mãe for objeto de uma exclusão.
- Se a tabela dependente também for uma tabela mãe, as ações descritas nesta lista serão aplicadas, por sua vez, às suas tabelas dependentes.

#### Exemplos

    -- restrição de chave primária no nível-de-coluna chamada PK_SAÍDA:
    CREATE TABLE SAMP.CAIXA_SAÍDA
            (
            ENVIO       TIMESTAMP,
            DESTINO     CHAR(8),
            ASSUNTO     CHAR(64) NOT NULL CONSTRAINT PK_CAIXA_SAÍDA PRIMARY KEY,
            TEXTO_NOTA  VARCHAR(3000)
       );

    -- a definição de chave primária no nível-de-tabela permite
    -- incluir duas colunas na definição da chave primária:
    CREATE TABLE SAMP.AGENDA
            (
            COD_CLASSE CHAR(7)  NOT NULL,
            DIA        SMALLINT NOT NULL,
            INÍCIO     TIME,
            FIM        TIME,
            PRIMARY KEY (COD_CLASSE, DIA)
            );

    -- Uso de uma restrição no nível-de-coluna para verificação aritmética.
    -- Uso de uma restrição no nível-de-tabela para ter certeza que os
    -- impostos do empregado não são maiores que os bônus.
    CREATE TABLE SAMP.EMP
            (
            NUM_EMP      CHAR(6)      NOT NULL CONSTRAINT PK_EMP PRIMARY KEY,
            NOME         CHAR(12)     NOT NULL,
            INICIAL_MEIO VARCHAR(12)  NOT NULL,
            SOBRENOME    VARCHAR(15)  NOT NULL,
            SALÁRIO      DECIMAL(9,2) CONSTRAINT VERIF_SAL CHECK (SALÁRIO >= 10000),
            BÔNUS        DECIMAL(9,2),
            IMPOSTOS     DECIMAL(9,2),
            CONSTRAINT VERIF_BÔNUS CHECK (BÔNUS > IMPOSTOS)
            );

    -- Uso de uma restrição de verificação para permitir
    -- apenas as abreviaturas apropriadas para as refeições
    CREATE TABLE VÔOS
            (
            ID_VÔO            CHAR(6) NOT NULL ,
            NÚMERO_SEGMENTO   INTEGER NOT NULL ,
            AEROPORTO_ORIGEM  CHAR(3),
            HORA_PARTIDA      TIME,
            AEROPORTO_DESTINO CHAR(3),
            HORA_CHEGADA      TIME,
            REFEIÇÃO          CHAR(1) CONSTRAINT VERIF_REFEIÇÃO
                                      CHECK (REFEIÇÃO IN ('B', 'L', 'D', 'S')),
            PRIMARY KEY (ID_VÔO, NÚMERO_SEGMENTO)
            );

    CREATE TABLE METROPOLITANO
            (
            ID_HOTEL   INT NOT NULL CONSTRAINT PK_HOTÉIS PRIMARY KEY,
            NOME_HOTEL VARCHAR(40) NOT NULL,
            ID_CIDADE  INT CONSTRAINT FK_METRO REFERENCES CIDADES
            );

    -- criação de uma tabela com uma restrição de chave primária
    -- e uma restrição de chave estrangeira no nível-de-tabela
    CREATE TABLE VÔOS_DISP
            (
            ID_VÔO                            CHAR(6) NOT NULL,
            NÚMERO_SEGMENTO                   INT NOT NULL,
            DATA_VÔO                          DATE NOT NULL,
            ASSENTOS_ECONÔMICOS_OCUPADOS      INT,
            ASSENTOS_EXECUTIVOS_OCUPADOS      INT,
            ASSENTOS_PRIMEIRA_CLASSE_OCUPADOS INT,
            CONSTRAINT PK_VÔOS_DISP PRIMARY KEY (ID_VÔO, NÚMERO_SEGMENTO),
            CONSTRAINT FK_VÔOS
                       FOREIGN KEY (ID_VÔO, NÚMERO_SEGMENTO)
                       REFERENCES VÔOS (ID_VÔO, NÚMERO_SEGMENTO)
            );

    -- adicionar uma restrição de unicidade a uma coluna
    ALTER TABLE SAMP.PROJETO
    ADD CONSTRAINT UNQ_PROJ UNIQUE (NOME_PROJ);

    -- criar uma tabela cuja coluna ID_CIDADE faça referência
    -- à chave primária da tabela CIDADES utilizando uma
    -- restrição de chave estrangeira no nível-de-coluna
    CREATE TABLE CONDOMÍNIOS
            (
            ID_COND   INT NOT NULL CONSTRAINT PK_HOTÉIS PRIMARY KEY,
            NOME_COND VARCHAR(40) NOT NULL,
            ID_CIDADE INT CONSTRAINT FK_CIDADE
                          REFERENCES CIDADES
                          ON DELETE CASCADE
                          ON UPDATE RESTRICT
            );

#### Sistema de dependência de instrução

As instruções INSERT e UPDATE dependem de todas as restrições da tabela de destino. As instruções DELETE dependem das restrições de unicidade, chave primária e de chave estrangeira. Estas instruções são invalidadas quando é adicionada ou removida uma restrição na tabela de destino.

- restrição no nível-de-coluna
- restrição no nível-de-tabela
- Especificação da referência
- CondiçãoProcura

Tópico pai: Instruções
Conceitos relacionados
Interação com o sistema de dependências
Instruções CREATE
Instruções DROP
Instruções RENAME
Instruções SET
Referências relacionadas
Instrução ALTER TABLE
CALL (PROCEDIMENTO)
Instrução DECLARE GLOBAL TEMPORARY TABLE
Instrução DELETE
Cláusula FOR UPDATE
Cláusula FROM
Cláusula GROUP BY
Cláusula HAVING
INNER JOIN
Instrução INSERT
Operação JOIN
LEFT OUTER JOIN
Instrução LOCK TABLE
Cláusula ORDER BY
Consulta
RIGHT OUTER JOIN
SubconsultaEscalar
ExpressãoSeleção
Instrução SELECT
ExpressãoTabela
SubconsultaTabela
Instrução UPDATE
VALUES Expressão
Cláusula WHERE
Cláusula WHERE CURRENT OF