sql >> Databasteknik >  >> RDS >> Sqlserver

Hur man hittar alla begränsningsöverträdelser i en SQL Server-databas

Du kan köra DBCC CHECKCONSTRAINTS console-kommandot för att returnera en lista över alla begränsningsöverträdelser i en SQL Server-databas.

Det här kommandot kontrollerar integriteten för en specificerad begränsning eller alla begränsningar på en specificerad tabell i den aktuella databasen. Den returnerar valfri främmande nyckel och CHECK begränsningsöverträdelser som den finner.

Du kan använda ALL_CONSTRAINTS alternativet för att kontrollera både aktiverade och inaktiverade begränsningar. Om du utelämnar detta returneras endast aktiverade begränsningar (såvida du inte uttryckligen anger en begränsning att kontrollera, i vilket fall kommer den att returneras oavsett om den är aktiverad eller inaktiverad).

Exempel 1 – Överträdda CHECK-begränsningar

Jag körde det här exemplet mot en databas som innehåller någon CHECK överträdelser av begränsningar.

USE Test;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultat:

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

Detta visar att jag har tre begränsningsöverträdelser i min databas.

Förklaring av kolumnerna

De tre kolumnerna returnerar följande information:

Tabell
Namnet på tabellnamnet som innehåller begränsningsöverträdelsen.
Begränsning
Namn på begränsningen som överträtts.
Var
Kolumnvärdestilldelningar som identifierar raden eller raderna som bryter mot begränsningen. Värdet i den här kolumnen kan användas i en WHERE sats av en SELECT sats som frågar efter rader som bryter mot begränsningen.

Därför, tack vare den tredje kolumnen, kan jag nu hitta (och uppdatera) alla ogiltiga data.

Hitta ogiltiga data

Så om vi tittar på den första raden från min DBCC CHECKCONSTRAINTS resultat ser vi att vi kan hitta de kränkande uppgifterna genom att använda [JobTitle] = 'Digital Nomad' i en WHERE klausul.

Så här:

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

Resultat:

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

Begränsningens definition

Låt oss ta en titt på den faktiska definitionen för chkJobTitle begränsning:

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

Resultat:

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

Denna begränsning säger att värdet på JobTitle kolumnen får inte vara Digital Nomad , men ändå lyckades en digital nomad komma in i min databas!

Uppdatera de stötande uppgifterna

Du kan antingen uppdatera den kränkande informationen, ta bort den eller lämna den ifred.

I det här exemplet använder jag samma WHERE sats för att uppdatera värdet:

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

Om jag nu kör kontrollen igen är den posten inte längre ett problem, och bara de andra två problemen kvarstår:

DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultat:

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

Exempel 2 – Överträdda begränsningar för främmande nyckel

I det här exemplet byter jag till en databas som innehåller ett par överträdelser av främmande nyckelbegränsningar.

USE Music;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultat:

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

I det här fallet verkar det som om två rader i Album tabell hänvisar till ett ArtistId som inte finns.

Hitta ogiltiga data

Återigen kan vi använda Var kolumn för att konstruera vår WHERE klausul. Den här gången lägger jag till båda överträdelserna i min WHERE klausul:

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

Resultat:

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

Så vi kan nu se de två raderna som bryter mot begränsningen (även om det bara är ArtistId kolumn som bryter mot begränsningen).

Kontrollera tabellen med primärnyckel

Vi kan bekräfta överträdelsen genom att fråga Artister tabell (dvs tabellen som innehåller primärnyckeln för denna främmande nyckel).

Så låt oss köra samma fråga mot Artister bord.

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

Resultat:

(0 rows affected)

Som väntat finns ingetdera värdet i den tabellen.

Den främmande nyckeln är tänkt att förhindra att detta händer. Antingen kom den ogiltiga informationen in i databasen medan den främmande nyckeln var inaktiverad, eller så kom den in innan den främmande nyckeln skapades. Oavsett vilket, när du skapar eller aktiverar en främmande nyckel eller CHECK begränsning, bör du använda WITH CHECK för att ange att alla befintliga data ska kontrolleras innan begränsningen aktiveras.

Exempel 3 – Markera Endast aktiverade begränsningar

Om du bara vill kontrollera begränsningar som för närvarande är aktiverade, ta bort WITH ALL_CONSTRAINTS :

USE Test;
DBCC CHECKCONSTRAINTS;

Resultat:

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

Så av de två begränsningarna som överträddes verkar det som om chkJobTitle är den enda som var aktiverad.

Vi kan verifiera detta ytterligare med följande fråga:

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

Resultat:

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

Exempel 4 – Markera endast begränsningar för en given tabell

Du kan lägga till namnet på en tabell inom parentes om du bara vill kontrollera begränsningarna för den tabellen:

USE Test;
DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;

Resultat:

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

Exempel 5 – Kontrollera en enda begränsning

Du kan kontrollera en enskild begränsning genom att omge dess namn inom parentes:

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate);

Resultat:

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

När du anger en enskild begränsning visas WITH ALL_CONSTRAINTS har ingen effekt:

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;

Resultat:

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

  1. Hur räknar man alla rader när man använder SELECT med LIMIT i MySQL-frågan?

  2. Ta bort alla dubbletter av rader utom en i MySQL?

  3. Förstå SQL Server ALTER TABLE ADD COLUMN Statement

  4. Hur man skapar PL/SQL lagrade procedurer utan parametrar i Oracle Database