Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment trouver toutes les violations de contraintes dans une base de données SQL Server

Vous pouvez exécuter le DBCC CHECKCONSTRAINTS console pour renvoyer une liste de toutes les violations de contrainte dans une base de données SQL Server.

Cette commande vérifie l'intégrité d'une contrainte spécifiée ou de toutes les contraintes sur une table spécifiée dans la base de données courante. Il renvoie n'importe quelle clé étrangère et CHECK violations de contrainte qu'il trouve.

Vous pouvez utiliser le ALL_CONSTRAINTS option pour vérifier les contraintes activées et désactivées. Si vous l'omettez, seules les contraintes activées sont renvoyées (sauf si vous spécifiez explicitement une contrainte à vérifier, auquel cas elle sera renvoyée, qu'elle soit activée ou désactivée).

Exemple 1 :Violation des contraintes CHECK

J'ai exécuté cet exemple sur une base de données contenant des CHECK violations de contraintes.

USE Test;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Résultat :

+------------------------+-------------------+---------------------------------------------------------+
| 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' |
+------------------------+-------------------+---------------------------------------------------------+

Cela montre que j'ai trois violations de contrainte dans ma base de données.

Explication des colonnes

Les trois colonnes renvoient les informations suivantes :

Tableau
Nom du nom de la table qui contient la violation de contrainte.
Contrainte
Nom de la contrainte violée.
Affectations de valeurs de colonne qui identifient la ou les lignes violant la contrainte. La valeur de cette colonne peut être utilisée dans un WHERE clause d'un SELECT instruction interrogeant les lignes qui violent la contrainte.

Par conséquent, grâce à la troisième colonne, je peux maintenant trouver (et mettre à jour) toutes les données invalides.

Rechercher les données invalides

Donc, si nous regardons la première ligne de mon DBCC CHECKCONSTRAINTS résultats, nous voyons que nous pouvons trouver les données incriminées en utilisant [JobTitle] = 'Digital Nomad' dans un WHERE clause.

Comme ceci :

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

Résultat :

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

La définition de la contrainte

Jetons un coup d'œil à la définition réelle du chkJobTitle contrainte :

SELECT Definition 
FROM sys.check_constraints
WHERE name = 'chkJobTitle';

Résultat :

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

Cette contrainte indique que la valeur de JobTitle la colonne ne doit pas être Nomade Numérique , pourtant un nomade digital a quand même réussi à entrer dans ma base de données !

Mettre à jour les données incriminées

Vous pouvez soit mettre à jour les données incriminées, les supprimer ou les laisser telles quelles.

Dans cet exemple, j'utilise le même WHERE clause pour mettre à jour la valeur :

UPDATE [dbo].[Occupation]
SET [JobTitle] = 'Unemployed'
WHERE [JobTitle] = 'Digital Nomad';

Maintenant, si je relance la vérification, cet enregistrement n'est plus un problème, et seuls les deux autres problèmes subsistent :

DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Résultat :

+------------------------+-------------------+---------------------------------------------------------+
| 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' |
+------------------------+-------------------+---------------------------------------------------------+

Exemple 2 :Violation des contraintes de clé étrangère

Dans cet exemple, je passe à une base de données qui contient quelques violations de contraintes de clé étrangère.

USE Music;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Résultat :

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

Dans ce cas, il semble que deux lignes dans les Albums table font référence à un ArtistId ça n'existe pas.

Rechercher les données invalides

Encore une fois, nous pouvons utiliser le colonne pour construire notre WHERE clause. Cette fois, j'ajouterai les deux violations à mon WHERE clause :

SELECT *
FROM [dbo].[Albums]
WHERE [ArtistId] = '123' OR [ArtistId] = '17';

Résultat :

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

Nous pouvons donc maintenant voir les deux lignes qui violent la contrainte (bien que ce ne soit que l' ArtistId colonne qui viole la contrainte).

Vérifiez la table de clé primaire

Nous pouvons confirmer la violation en interrogeant les Artistes table (c'est-à-dire la table qui contient la clé primaire de cette clé étrangère).

Exécutons donc la même requête sur les Artistes tableau.

SELECT *
FROM [dbo].[Artists]
WHERE [ArtistId] = '123' OR [ArtistId] = '17';

Résultat :

(0 rows affected)

Comme prévu, aucune valeur n'est dans cette table.

La clé étrangère est censée empêcher que cela se produise. Soit les données non valides sont entrées dans la base de données alors que la clé étrangère était désactivée, soit elles sont entrées avant la création de la clé étrangère. Dans tous les cas, lors de la création ou de l'activation d'une clé étrangère ou de CHECK contrainte, vous devez utiliser WITH CHECK pour spécifier que toutes les données existantes doivent être vérifiées avant d'activer la contrainte.

Exemple 3 - Vérifier uniquement les contraintes activées

Si vous souhaitez uniquement vérifier les contraintes actuellement activées, supprimez WITH ALL_CONSTRAINTS :

USE Test;
DBCC CHECKCONSTRAINTS;

Résultat :

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

Ainsi, sur les deux contraintes qui ont été violées, il semble que chkJobTitle est le seul qui a été activé.

Nous pouvons vérifier cela avec la requête suivante :

SELECT 
  name,
  is_disabled
FROM sys.check_constraints
WHERE name = 'chkValidEndDate' OR name = 'chkJobTitle';

Résultat :

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

Exemple 4 - Vérifier uniquement les contraintes pour une table donnée

Vous pouvez ajouter le nom d'une table entre parenthèses si vous souhaitez uniquement vérifier les contraintes de cette table :

USE Test;
DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;

Résultat :

+------------------------+-------------------+---------------------------------------------------------+
| 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' |
+------------------------+-------------------+---------------------------------------------------------+

Exemple 5 - Vérifier une seule contrainte

Vous pouvez vérifier une seule contrainte en plaçant son nom entre parenthèses :

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate);

Résultat :

+------------------------+-------------------+---------------------------------------------------------+
| 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' |
+------------------------+-------------------+---------------------------------------------------------+

Lorsque vous spécifiez une seule contrainte, le WITH ALL_CONSTRAINTS n'a aucun effet :

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;

Résultat :

+------------------------+-------------------+---------------------------------------------------------+
| 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' |
+------------------------+-------------------+---------------------------------------------------------+