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