Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

So finden Sie alle Einschränkungsverletzungen in einer SQL Server-Datenbank

Sie können DBCC CHECKCONSTRAINTS ausführen console-Befehl, um eine Liste aller Beschränkungsverletzungen in einer SQL Server-Datenbank zurückzugeben.

Dieser Befehl prüft die Integrität einer angegebenen Einschränkung oder aller Einschränkungen für eine angegebene Tabelle in der aktuellen Datenbank. Es gibt einen beliebigen Fremdschlüssel und CHECK zurück Einschränkungsverletzungen, die es findet.

Sie können die ALL_CONSTRAINTS verwenden Option, um sowohl aktivierte als auch deaktivierte Einschränkungen zu überprüfen. Wenn Sie dies weglassen, werden nur aktivierte Einschränkungen zurückgegeben (es sei denn, Sie geben explizit eine zu prüfende Einschränkung an, in diesem Fall wird sie unabhängig davon zurückgegeben, ob sie aktiviert oder deaktiviert ist).

Beispiel 1 – Verletzung von CHECK-Einschränkungen

Ich habe dieses Beispiel mit einer Datenbank ausgeführt, die CHECK enthält Beschränkungsverletzungen.

USE Test;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Ergebnis:

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

Dies zeigt, dass ich drei Beschränkungsverletzungen in meiner Datenbank habe.

Erklärung der Spalten

Die drei Spalten geben die folgenden Informationen zurück:

Tabelle
Name des Tabellennamens, der die Einschränkungsverletzung enthält.
Einschränkung
Name der Einschränkung, die verletzt wird.
Wo
Spaltenwertzuweisungen, die die Zeile oder Zeilen identifizieren, die gegen die Beschränkung verstoßen. Der Wert in dieser Spalte kann in einem WHERE verwendet werden -Klausel eines SELECT -Anweisung, die Zeilen abfragt, die gegen die Einschränkung verstoßen.

Daher kann ich dank der dritten Spalte jetzt alle ungültigen Daten finden (und aktualisieren).

Ungültige Daten finden

Betrachten wir also die erste Zeile meiner DBCC CHECKCONSTRAINTS Ergebnisse sehen wir, dass wir die anstößigen Daten finden können, indem wir [JobTitle] = 'Digital Nomad' verwenden in einem WHERE Klausel.

So:

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

Ergebnis:

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

Die Beschränkungsdefinition

Werfen wir einen Blick auf die eigentliche Definition für chkJobTitle Einschränkung:

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

Ergebnis:

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

Diese Einschränkung besagt, dass der Wert von JobTitle Spalte darf nicht sein sei Digitaler Nomade , dennoch hat es ein digitaler Nomade geschafft, in meine Datenbank einzudringen!

Aktualisieren Sie die anstößigen Daten

Sie können die anstößigen Daten entweder aktualisieren, löschen oder in Ruhe lassen.

In diesem Beispiel verwende ich dasselbe WHERE -Klausel zum Aktualisieren des Werts:

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

Wenn ich die Prüfung jetzt erneut durchführe, ist dieser Datensatz kein Problem mehr, und nur die anderen beiden Probleme bleiben bestehen:

DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Ergebnis:

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

Beispiel 2 – Verletzung von Foreign Key Constraints

In diesem Beispiel wechsle ich zu einer Datenbank, die ein paar Verletzungen von Fremdschlüsselbeschränkungen enthält.

USE Music;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Ergebnis:

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

In diesem Fall scheinen zwei Zeilen in den Alben Tabelle verweisen auf eine ArtistId das gibt es nicht.

Ungültige Daten finden

Auch hier können wir das Where verwenden Spalte, um unser WHERE zu konstruieren Klausel. Dieses Mal füge ich beide Verstöße meinem WHERE hinzu Klausel:

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

Ergebnis:

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

Wir können also jetzt die beiden Zeilen sehen, die gegen die Einschränkung verstoßen (obwohl es nur die ArtistId ist Spalte, die gegen die Beschränkung verstößt).

Prüfen Sie die Primärschlüsseltabelle

Wir können den Verstoß bestätigen, indem wir die Künstler befragen Tabelle (d. h. die Tabelle, die den Primärschlüssel für diesen Fremdschlüssel enthält).

Lassen Sie uns also dieselbe Abfrage für die Artists ausführen Tabelle.

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

Ergebnis:

(0 rows affected)

Wie erwartet ist keiner der Werte in dieser Tabelle enthalten.

Der Fremdschlüssel soll dies verhindern. Entweder wurden die ungültigen Daten in die Datenbank eingegeben, während der Fremdschlüssel deaktiviert war, oder sie wurden eingegeben, bevor der Fremdschlüssel erstellt wurde. So oder so, beim Erstellen oder Aktivieren eines Fremdschlüssels oder CHECK Beschränkung, sollten Sie WITH CHECK verwenden um anzugeben, dass alle vorhandenen Daten überprüft werden sollen, bevor die Einschränkung aktiviert wird.

Beispiel 3 – Nur aktivierte Beschränkungen prüfen

Wenn Sie nur die derzeit aktivierten Einschränkungen überprüfen möchten, entfernen Sie WITH ALL_CONSTRAINTS :

USE Test;
DBCC CHECKCONSTRAINTS;

Ergebnis:

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

Von den beiden verletzten Einschränkungen scheint also chkJobTitle ist die einzige, die aktiviert wurde.

Wir können dies weiter mit der folgenden Abfrage überprüfen:

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

Ergebnis:

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

Beispiel 4 – Nur Einschränkungen für eine gegebene Tabelle prüfen

Sie können den Namen einer Tabelle in Klammern hinzufügen, wenn Sie nur die Einschränkungen für diese Tabelle überprüfen möchten:

USE Test;
DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;

Ergebnis:

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

Beispiel 5 – Prüfen einer einzelnen Einschränkung

Sie können eine einzelne Einschränkung überprüfen, indem Sie ihren Namen in Klammern einschließen:

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate);

Ergebnis:

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

Wenn Sie eine einzelne Einschränkung angeben, wird WITH ALL_CONSTRAINTS hat keine Auswirkung:

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;

Ergebnis:

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