Můžete spustit DBCC CHECKCONSTRAINTS
konzole, abyste vrátili seznam všech porušení omezení v databázi SQL Server.
Tento příkaz zkontroluje integritu zadaného omezení nebo všech omezení na zadané tabulce v aktuální databázi. Vrátí jakýkoli cizí klíč a CHECK
porušení omezení, která zjistí.
Můžete použít ALL_CONSTRAINTS
možnost zkontrolovat povolená i zakázaná omezení. Pokud toto vynecháte, vrátí se pouze povolená omezení (pokud výslovně neurčíte omezení ke kontrole, v takovém případě bude vráceno bez ohledu na to, zda je povoleno nebo zakázáno).
Příklad 1 – Porušení omezení CHECK
Spustil jsem tento příklad proti databázi, která obsahuje nějaké CHECK
porušení omezení.
USE Test; DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;
Výsledek:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
To ukazuje, že mám ve své databázi tři porušení omezení.
Vysvětlení sloupců
Tři sloupce vracejí následující informace:
- Tabulka
- Název názvu tabulky, který obsahuje porušení omezení.
- Omezení
- Název omezení, které je porušeno.
- Kde
- Přiřazení hodnot sloupců, které identifikují řádek nebo řádky porušující omezení. Hodnotu v tomto sloupci lze použít v
WHERE
klauzuleSELECT
příkaz dotazující se na řádky, které porušují omezení.
Díky třetímu sloupci tedy nyní mohu najít (a aktualizovat) všechna neplatná data.
Najděte neplatná data
Takže když se podíváme na první řádek z mého DBCC CHECKCONSTRAINTS
výsledků, vidíme, že můžeme najít problematická data pomocí [JobTitle] = 'Digital Nomad'
v WHERE
doložka.
Takhle:
SELECT * FROM [dbo].[Occupation] WHERE [JobTitle] = 'Digital Nomad';
Výsledek:
+----------------+---------------+ | OccupationId | JobTitle | |----------------+---------------| | 7 | Digital Nomad | +----------------+---------------+
Definice omezení
Podívejme se na skutečnou definici chkJobTitle
omezení:
SELECT Definition FROM sys.check_constraints WHERE name = 'chkJobTitle';
Výsledek:
+-------------------------------+ | Definition | |-------------------------------| | ([JobTitle]<>'Digital Nomad') | +-------------------------------+
Toto omezení říká, že hodnota JobTitle sloupec nemusí být Digitální nomád , přesto se digitálnímu nomádovi podařilo dostat do mé databáze!
Aktualizujte údaje o přestupcích
Data můžete buď aktualizovat, smazat nebo je nechat být.
V tomto příkladu používám stejné WHERE
klauzule pro aktualizaci hodnoty:
UPDATE [dbo].[Occupation] SET [JobTitle] = 'Unemployed' WHERE [JobTitle] = 'Digital Nomad';
Nyní, když znovu spustím kontrolu, tento záznam již nepředstavuje problém a zůstávají pouze zbývající dva problémy:
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;
Výsledek:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
Příklad 2 – Porušení omezení cizího klíče
V tomto příkladu přepnu do databáze, která obsahuje několik porušení omezení cizího klíče.
USE Music; DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;
Výsledek:
+----------------+---------------------+--------------------+ | Table | Constraint | Where | |----------------+---------------------+--------------------| | [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '123' | | [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '17' | +----------------+---------------------+--------------------+
V tomto případě se zdá, že dva řádky v Albech tabulka odkazuje na ArtistId který neexistuje.
Najděte neplatná data
Opět můžeme použít
Kde
sloupec k vytvoření našeho WHERE
doložka. Tentokrát přidám obě porušení do svého WHERE
klauzule:
SELECT * FROM [dbo].[Albums] WHERE [ArtistId] = '123' OR [ArtistId] = '17';
Výsledek:
+-----------+-------------+---------------+------------+-----------+ | AlbumId | AlbumName | ReleaseDate | ArtistId | GenreId | |-----------+-------------+---------------+------------+-----------| | 21 | Yo Wassup | 2019-03-12 | 17 | 3 | | 22 | Busted | 1901-05-11 | 123 | 3 | +-----------+-------------+---------------+------------+-----------+
Nyní tedy vidíme dva řádky, které porušují omezení (ačkoli je to pouze ArtistId sloupec, který porušuje omezení).
Zkontrolujte tabulku primárních klíčů
Porušení můžeme potvrdit dotazem Umělci tabulka (tj. tabulka, která obsahuje primární klíč pro tento cizí klíč).
Spusťte tedy stejný dotaz proti Umělci tabulka.
SELECT * FROM [dbo].[Artists] WHERE [ArtistId] = '123' OR [ArtistId] = '17';
Výsledek:
(0 rows affected)
Jak se očekávalo, ani jedna hodnota není v této tabulce.
Tomu má zabránit cizí klíč. Neplatná data vstoupila do databáze v době, kdy byl cizí klíč zakázán, nebo byla zadána před vytvořením cizího klíče. Ať tak či onak, při vytváření nebo povolení cizího klíče nebo CHECK
omezení, měli byste použít WITH CHECK
určit, že před povolením omezení by měla být zkontrolována všechna existující data.
Příklad 3 – Zaškrtněte pouze povolená omezení
Pokud chcete zkontrolovat pouze omezení, která jsou aktuálně povolena, odstraňte WITH ALL_CONSTRAINTS
:
USE Test; DBCC CHECKCONSTRAINTS;
Výsledek:
+--------------------+---------------+------------------------------+ | Table | Constraint | Where | |--------------------+---------------+------------------------------| | [dbo].[Occupation] | [chkJobTitle] | [JobTitle] = 'Digital Nomad' | +--------------------+---------------+------------------------------+
Takže ze dvou omezení, která byla porušena, se zdá, že chkJobTitle je jediný, který byl povolen.
Můžeme to dále ověřit pomocí následujícího dotazu:
SELECT name, is_disabled FROM sys.check_constraints WHERE name = 'chkValidEndDate' OR name = 'chkJobTitle';
Výsledek:
+-----------------+---------------+ | name | is_disabled | |-----------------+---------------| | chkJobTitle | 0 | | chkValidEndDate | 1 | +-----------------+---------------+
Příklad 4 – Kontrola pouze omezení pro danou tabulku
Název tabulky můžete přidat do závorek, pokud chcete pouze zkontrolovat omezení pro danou tabulku:
USE Test; DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;
Výsledek:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
Příklad 5 – Kontrola jednoho omezení
Jedno omezení můžete zkontrolovat uzavřením jeho názvu do závorek:
USE Test; DBCC CHECKCONSTRAINTS(chkValidEndDate);
Výsledek:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
Když zadáte jediné omezení, WITH ALL_CONSTRAINTS
nemá žádný účinek:
USE Test; DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;
Výsledek:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+