sql >> Databáze >  >> RDS >> Sqlserver

Jak najít všechna porušení omezení v databázi SQL Server

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

  1. MySQL „vytvořit schéma“ a „vytvořit databázi“ – Existuje nějaký rozdíl?

  2. Jak vytvářet a manipulovat s databázemi SQL pomocí Pythonu

  3. vytvořit tabulku se sekvencí.nextval v oracle

  4. Skupiny konverzace SQL Server Service Broker