Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como criar uma restrição CHECK no SQL Server (Exemplos de T-SQL)


No SQL Server você pode criar um CHECK restrição em uma tabela para especificar os valores de dados que são aceitáveis ​​em uma ou mais colunas.

Se uma tabela tiver um CHECK restrição sobre ele, e você tenta fornecer dados que não estão de acordo com o CHECK restrição, a operação falhará com um erro.

Isso ajuda a manter a integridade dos dados, pois ajuda a evitar que dados inválidos entrem no banco de dados.

Quando você cria um CHECK restrição, você fornece uma expressão lógica que retorna TRUE ou FALSE . Essa expressão lógica é o que é usado para verificar os dados.

CHECK As restrições são semelhantes às restrições de chave estrangeira porque controlam os valores que são colocados em uma coluna. No entanto, a diferença está em como eles determinam quais valores são válidos:restrições de chave estrangeira obtêm a lista de valores válidos de outra tabela, enquanto CHECK restrições determinam os valores válidos de uma expressão lógica.

As restrições podem ser definidas no nível da coluna ou da tabela. Uma restrição de nível de coluna se aplica apenas aos dados dessa coluna. Uma restrição de nível de tabela se aplica a toda a linha e verifica os dados de várias colunas.

Abaixo estão exemplos de criação de nível de coluna e de tabela CHECK restrições.


Exemplo 1 – Criar uma restrição CHECK em nível de coluna


Aqui está um exemplo de criação de um CHECK básico em nível de coluna restrição no momento da criação de uma tabela.
CREATE TABLE ConstraintTest
(
  ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  Price smallmoney NOT NULL,
  CONSTRAINT chkPrice CHECK (Price > 0)
);

Neste caso, o CHECK restrição especifica que todos os dados no Price coluna deve ser maior que 0. Em outras palavras, o preço não pode ser zero e não pode ser negativo. Essa é uma restrição de nível de coluna porque se aplica a dados em uma coluna.

Como essa é uma restrição de nível de coluna, eu poderia tê-la definido como parte da coluna (sem a vírgula). Então eu poderia ter feito isso:
CREATE TABLE ConstraintTest
(
  ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0)
);

De qualquer forma, vamos tentar inserir um valor inválido:
INSERT INTO ConstraintTest ( Price )
VALUES ( 0 );

Resultado:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkPrice". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'Price'.

Exemplo 2 - Adicionar mais colunas e outra restrição CHECK em nível de coluna


Vamos adicionar mais algumas colunas à nossa tabela e, em seguida, adicionar outro nível de coluna CHECK limitação.
ALTER TABLE ConstraintTest
ADD 
  TeamSize tinyint NOT NULL,
  StartDate date NOT NULL,
  EndDate date NOT NULL,
  CONSTRAINT chkTeamSize CHECK (TeamSize >= 3 AND TeamSize <= 15)
  ;

Uma das novas colunas registra o número de membros da equipe. Nesse caso, a regra de negócio é que uma equipe deve ter pelo menos 3 membros, mas não mais que 15. Portanto, o banco de dados deve evitar a situação em que uma equipe tenha menos de 3 membros ou mais de 15.

Vamos tentar inserir um valor inválido:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 2, '2020-01-01', '1900-02-02' );

Resultado:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.

Exemplo 3 - Adicionar uma restrição CHECK em nível de tabela


Agora vamos adicionar uma restrição de nível de tabela. Isso verificará os dados em duas colunas.

A propósito, você não precisa adicionar outra coluna para adicionar um CHECK limitação. Você pode simplesmente adicionar a restrição por si só.

Exemplo:
ALTER TABLE ConstraintTest
  ADD CONSTRAINT chkValidEndDate 
  CHECK (EndDate >= StartDate)
  ;

Nesse caso, adiciono uma restrição para garantir que a data de término nunca seja anterior à data de início. Isso está verificando dados em duas colunas e, portanto, é uma restrição de nível de tabela.

Tente inserir um valor inválido:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 3, '2020-01-01', '1900-02-02' );

Resultado:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".

Observe que, para testar essa restrição, tive que aumentar os membros da equipe para 3 para evitar que a restrição anterior fosse acionada primeiro (CHECK restrições são validadas na ordem em que são criadas).

Exemplo 4 – Alterar uma restrição CHECK


Você não pode alterar um CHECK limitação. Se você precisar alterá-lo, precisará soltá-lo e criá-lo com a nova definição.

Exemplo:
ALTER TABLE ConstraintTest 
  DROP CONSTRAINT chkTeamSize;

ALTER TABLE ConstraintTest
  ADD CONSTRAINT chkTeamSize 
  CHECK (TeamSize >= 5 AND TeamSize <= 20)
  ;

Como mencionado, CHECK as restrições são validadas na ordem em que são criadas, portanto, isso pode afetar qual erro é detectado primeiro.

Portanto, neste caso, se eu tentar inserir um valor inválido (e também incluir datas inválidas), as datas inválidas serão capturadas primeiro:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 4, '2020-01-01', '1900-02-02' );

Resultado:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".

Portanto, para verificar minha restrição mais recente, precisarei corrigir o problema de data primeiro:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 4, '2020-01-01', '2020-02-02' );

Resultado:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.

Portanto, minha última restrição está funcionando conforme o esperado.

Exemplo 5 – VERIFICAR Restrições e Colunas de IDENTIDADE


Agora que testamos as restrições, vamos em frente e inserir dados válidos:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 5, '2020-01-01', '2020-02-02' );

Resultado:
+--------------------+---------+------------+-------------+------------+
| ConstraintTestId   | Price   | TeamSize   | StartDate   | EndDate    |
|--------------------+---------+------------+-------------+------------|
| 13                 | 1.0000  | 5          | 2020-01-01  | 2020-02-02 |
+--------------------+---------+------------+-------------+------------+

Finalmente, obtemos uma inserção bem-sucedida.

No entanto, você notará que a IDENTITY coluna já foi incrementada para 13.

Lembre-se quando criei a tabela pela primeira vez, defini o ConstraintTestId coluna para usar IDENTITY(1,1) , o que significa que deve começar em 1 e incrementar automaticamente em 1 com cada inserção de linha.

Mas agora que finalmente inseri minha primeira linha, o valor já é 13. Isso porque a IDENTITY coluna é incrementada mesmo quando um CHECK restrição faz com que o INSERT operação falhar.

Observe que eu fiz algumas inserções extras com falha enquanto criava os exemplos para este artigo, então o valor foi incrementado para um valor mais alto do que o que você obterá se você simplesmente seguir passo a passo este artigo.

De qualquer forma, vamos fazer uma última inserção com falha e, em seguida, uma bem-sucedida para confirmar isso.

Falha na inserção:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 2, 4, '2020-01-02', '2020-02-03' );

Resultado:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.

Inserção bem-sucedida:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 2, 6, '2020-01-02', '2020-02-03' );

SELECT * FROM ConstraintTest;

Resultado:
+--------------------+---------+------------+-------------+------------+
| ConstraintTestId   | Price   | TeamSize   | StartDate   | EndDate    |
|--------------------+---------+------------+-------------+------------|
| 13                 | 1.0000  | 5          | 2020-01-01  | 2020-02-02 |
| 15                 | 2.0000  | 6          | 2020-01-02  | 2020-02-03 |
+--------------------+---------+------------+-------------+------------+

Podemos ver que a IDENTITY A coluna salta de 13 para 15, então obviamente é incrementada durante a inserção com falha.

Algumas restrições das restrições CHECK


Aqui estão algumas restrições a serem observadas ao trabalhar com CHECK restrições:
  • A condição de pesquisa deve ser avaliada como uma expressão booleana e não pode fazer referência a outra tabela.
  • A expressão não pode conter tipos de dados de alias.
  • CHECK restrições não podem ser definidas em texto , ntext , ou imagem colunas.