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

Como encontrar todas as violações de restrição em um banco de dados SQL Server


Você pode executar o DBCC CHECKCONSTRAINTS comando console para retornar uma lista de todas as violações de restrição em um banco de dados SQL Server.

Este comando verifica a integridade de uma restrição especificada ou de todas as restrições em uma tabela especificada no banco de dados atual. Ele retorna qualquer chave estrangeira e CHECK violações de restrição que encontrar.

Você pode usar o ALL_CONSTRAINTS opção para verificar as restrições habilitadas e desabilitadas. Se você omitir isso, apenas as restrições habilitadas serão retornadas (a menos que você especifique explicitamente uma restrição a ser verificada, caso em que ela será retornada independentemente de estar habilitada ou desabilitada).


Exemplo 1 – Restrições de VERIFICAÇÃO violadas


Eu executei este exemplo em um banco de dados que contém alguns CHECK violações de restrições.
USE Test;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultado:
+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[Occupation]     | [chkJobTitle]     | [JobTitle] = 'Digital Nomad'                            |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Isso mostra que tenho três violações de restrição no meu banco de dados.

Explicação das Colunas


As três colunas retornam as seguintes informações:
Tabela
Nome do nome da tabela que contém a violação de restrição.
Restrição
Nome da restrição que foi violada.
Onde
Atribuições de valor de coluna que identificam a linha ou linhas que violam a restrição. O valor nesta coluna pode ser usado em um WHERE cláusula de um SELECT instrução consultando linhas que violam a restrição.

Portanto, graças à terceira coluna, agora posso encontrar (e atualizar) todos os dados inválidos.

Encontre os dados inválidos


Então, se olharmos para a primeira linha do meu DBCC CHECKCONSTRAINTS resultados, vemos que podemos encontrar os dados incorretos usando [JobTitle] = 'Digital Nomad' em um WHERE cláusula.

Assim:
SELECT *
FROM [dbo].[Occupation]
WHERE [JobTitle] = 'Digital Nomad';

Resultado:
+----------------+---------------+
| OccupationId   | JobTitle      |
|----------------+---------------|
| 7              | Digital Nomad |
+----------------+---------------+

A definição de restrição


Vamos dar uma olhada na definição real para o chkJobTitle limitação:
SELECT Definition 
FROM sys.check_constraints
WHERE name = 'chkJobTitle';

Resultado:
+-------------------------------+
| Definition                    |
|-------------------------------|
| ([JobTitle]<>'Digital Nomad') |
+-------------------------------+

Essa restrição diz que o valor do JobTitle a coluna deve não seja Nômade Digital , mas um nômade digital ainda conseguiu entrar no meu banco de dados!

Atualize os dados ofensivos


Você pode atualizar os dados incorretos, excluí-los ou deixá-los em paz.

Neste exemplo eu uso o mesmo WHERE cláusula para atualizar o valor:
UPDATE [dbo].[Occupation]
SET [JobTitle] = 'Unemployed'
WHERE [JobTitle] = 'Digital Nomad';

Agora, se eu executar a verificação novamente, esse registro não será mais um problema e apenas os outros dois problemas permanecerão:
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultado:
+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Exemplo 2 – Restrições de chave estrangeira violadas


Neste exemplo, alterno para um banco de dados que contém algumas violações de restrição de chave estrangeira.
USE Music;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultado:
+----------------+---------------------+--------------------+
| Table          | Constraint          | Where              |
|----------------+---------------------+--------------------|
| [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '123' |
| [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '17'  |
+----------------+---------------------+--------------------+

Nesse caso, parece que duas linhas em Álbuns table estão referenciando um ArtistId isso não existe.

Encontre os dados inválidos


Novamente, podemos usar o Where coluna para construir nosso WHERE cláusula. Desta vez, adicionarei as duas violações ao meu WHERE cláusula:
SELECT *
FROM [dbo].[Albums]
WHERE [ArtistId] = '123' OR [ArtistId] = '17';

Resultado:
+-----------+-------------+---------------+------------+-----------+
| AlbumId   | AlbumName   | ReleaseDate   | ArtistId   | GenreId   |
|-----------+-------------+---------------+------------+-----------|
| 21        | Yo Wassup   | 2019-03-12    | 17         | 3         |
| 22        | Busted      | 1901-05-11    | 123        | 3         |
+-----------+-------------+---------------+------------+-----------+

Assim, agora podemos ver as duas linhas que violam a restrição (embora seja apenas o ArtistId coluna que viola a restrição).

Verifique a Tabela de Chave Primária


Podemos confirmar a violação consultando os Artistas table (ou seja, a tabela que contém a chave primária para esta chave estrangeira).

Então, vamos executar a mesma consulta nos Artistas tabela.
SELECT *
FROM [dbo].[Artists]
WHERE [ArtistId] = '123' OR [ArtistId] = '17';

Resultado:
(0 rows affected)

Como esperado, nenhum valor está nessa tabela.

A chave estrangeira deve impedir que isso aconteça. Os dados inválidos entraram no banco de dados enquanto a chave estrangeira estava desativada ou entraram antes da criação da chave estrangeira. De qualquer forma, ao criar ou habilitar uma chave estrangeira ou CHECK restrição, você deve usar WITH CHECK para especificar que todos os dados existentes devem ser verificados antes de ativar a restrição.

Exemplo 3 – Verificar somente restrições habilitadas


Se você deseja apenas verificar as restrições que estão atualmente habilitadas, remova WITH ALL_CONSTRAINTS :
USE Test;
DBCC CHECKCONSTRAINTS;

Resultado:
+--------------------+---------------+------------------------------+
| Table              | Constraint    | Where                        |
|--------------------+---------------+------------------------------|
| [dbo].[Occupation] | [chkJobTitle] | [JobTitle] = 'Digital Nomad' |
+--------------------+---------------+------------------------------+

Assim, das duas restrições que foram violadas, parece que chkJobTitle é o único que foi habilitado.

Podemos verificar ainda mais isso com a seguinte consulta:
SELECT 
  name,
  is_disabled
FROM sys.check_constraints
WHERE name = 'chkValidEndDate' OR name = 'chkJobTitle';

Resultado:
+-----------------+---------------+
| name            | is_disabled   |
|-----------------+---------------|
| chkJobTitle     | 0             |
| chkValidEndDate | 1             |
+-----------------+---------------+

Exemplo 4 - Verificar apenas restrições para uma determinada tabela


Você pode adicionar o nome de uma tabela entre parênteses se quiser apenas verificar as restrições dessa tabela:
USE Test;
DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;

Resultado:
+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Exemplo 5 – Verificar uma única restrição


Você pode verificar uma única restrição colocando seu nome entre parênteses:
USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate);

Resultado:
+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Quando você especifica uma única restrição, o WITH ALL_CONSTRAINTS não tem efeito:
USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;

Resultado:
+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+