Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come trovare tutte le violazioni dei vincoli in un database di SQL Server

Puoi eseguire DBCC CHECKCONSTRAINTS comando console per restituire un elenco di tutte le violazioni dei vincoli in un database di SQL Server.

Questo comando verifica l'integrità di un vincolo specificato o di tutti i vincoli su una tabella specificata nel database corrente. Restituisce qualsiasi chiave esterna e CHECK violazioni dei vincoli che rileva.

Puoi usare ALL_CONSTRAINTS opzione per controllare sia i vincoli abilitati che quelli disabilitati. Se lo ometti, vengono restituiti solo i vincoli abilitati (a meno che tu non specifichi esplicitamente un vincolo da controllare, nel qual caso verrà restituito indipendentemente dal fatto che sia abilitato o disabilitato).

Esempio 1 – Vincoli CHECK violati

Ho eseguito questo esempio su un database che contiene alcuni CHECK violazioni dei vincoli.

USE Test;DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Risultato:

+--------------------------------------+------+- -------------------------------------------------- ------+| tavola | vincolo | Dove ||-------------------------+--------------------+-- -------------------------------------------------- -----|| [dbo].[Occupazione] | [chkTitolo lavoro] | [Titolo lavoro] ='Nomade digitale' || [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2020-01-01' AND [EndDate] ='1999-01-01' || [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2021-10-25' AND [EndDate] ='2021-10-24' |+-----------------------+ -------------------+----------------- ----------------------------+

Questo mostra che ho tre violazioni dei vincoli nel mio database.

Spiegazione delle colonne

Le tre colonne restituiscono le seguenti informazioni:

Tabella
Nome del nome della tabella che contiene la violazione del vincolo.
Vincolo
Nome del vincolo violato.
Dove
Assegnazioni di valori di colonna che identificano la riga o le righe che violano il vincolo. Il valore in questa colonna può essere utilizzato in un WHERE clausola di un SELECT istruzione che esegue query per righe che violano il vincolo.

Pertanto, grazie alla terza colonna, ora posso trovare (e aggiornare) tutti i dati non validi.

Trova i dati non validi

Quindi, se osserviamo la prima riga del mio DBCC CHECKCONSTRAINTS risultati, vediamo che possiamo trovare i dati offensivi usando [JobTitle] = 'Digital Nomad' in un WHERE clausola.

In questo modo:

SELEZIONARE *DA [dbo].[Occupazione]WHERE [Titolo lavoro] ='Nomade digitale';

Risultato:

+----------------+---------------+| ID occupazione | Titolo lavoro ||----------------+---------------|| 7 | Nomade digitale |+----------------+---------------+

La definizione del vincolo

Diamo un'occhiata alla definizione effettiva per il chkJobTitle vincolo:

SELEZIONA Definizione DA sys.check_constraintsWHERE name ='chkJobTitle';

Risultato:

+-------------------------------+| Definizione ||-----------------||| ([Titolo lavoro]<>'Nomade digitale') |+--------------------------------+

Questo vincolo dice che il valore di JobTitle la colonna deve non essere Nomade digitale , eppure un nomade digitale è comunque riuscito a entrare nel mio database!

Aggiorna i dati illeciti

Puoi aggiornare i dati offensivi, eliminarli o lasciarli soli.

In questo esempio utilizzo lo stesso WHERE clausola per aggiornare il valore:

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

Ora, se eseguo di nuovo il controllo, quel record non è più un problema e rimangono solo gli altri due problemi:

DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Risultato:

+--------------------------------------+------+- -------------------------------------------------- ------+| tavola | vincolo | Dove ||-------------------------+--------------------+-- -------------------------------------------------- -----|| [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2020-01-01' AND [EndDate] ='1999-01-01' || [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2021-10-25' AND [EndDate] ='2021-10-24' |+-----------------------+ -------------------+----------------- ----------------------------+

Esempio 2 – Vincoli di chiave esterna violati

In questo esempio passo a un database che contiene un paio di violazioni dei vincoli di chiave esterna.

USE Music;DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Risultato:

+----------------+--------+-------- -------------+| tavola | vincolo | Dove ||----------------+----------------------+--------- ------------|| [dbo].[Album] | [FK_Album_Artisti] | [ID artista] ='123' || [dbo].[Album] | [FK_Album_Artisti] | [ArtistId] ='17' |+----------------+----------------------+-- ---+

In questo caso, sembra che ci siano due righe negli Album la tabella fa riferimento a un ArtistId quello non esiste.

Trova i dati non validi

Ancora una volta, possiamo usare Dove colonna per costruire il nostro WHERE clausola. Questa volta aggiungerò entrambe le violazioni al mio WHERE clausola:

SELECT *FROM [dbo].[Album]WHERE [ArtistId] ='123' O [ArtistId] ='17';

Risultato:

+-----------+-------------+---------------+---- --------+------------+| IDAlbum | NomeAlbum | Data di rilascio | ID artista | GenereId ||-----------+-------------+---------------+----- -------+-----------|| 21 | Yo Wassup | 2019-03-12 | 17 | 3 || 22 | sballato | 11-05-1901 | 123 | 3 |+-----------+-------------+---------------+----- -------+-----------+

Quindi ora possiamo vedere le due righe che violano il vincolo (sebbene sia solo ArtistId colonna che viola il vincolo).

Controlla la tabella delle chiavi primarie

Possiamo confermare la violazione interrogando gli Artisti table (ovvero la tabella che contiene la chiave primaria per questa chiave esterna).

Quindi eseguiamo la stessa query sugli Artisti tabella.

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

Risultato:

(0 righe interessate)

Come previsto, nessuno dei due valori è in quella tabella.

La chiave esterna dovrebbe impedire che ciò accada. I dati non validi sono entrati nel database mentre la chiave esterna era disabilitata o sono stati inseriti prima della creazione della chiave esterna. In entrambi i casi, quando si crea o si abilita una chiave esterna o CHECK vincolo, dovresti usare WITH CHECK per specificare che tutti i dati esistenti devono essere controllati prima di abilitare il vincolo.

Esempio 3:spunta solo i vincoli abilitati

Se vuoi controllare solo i vincoli attualmente abilitati, rimuovi WITH ALL_CONSTRAINTS :

Test USE;CONTROLLO VINCOLI DBCC;

Risultato:

+--------------------+---------------+--------- ---------------------+| tavola | vincolo | Dove ||--------------------+---------------+---------- --------------------|| [dbo].[Occupazione] | [chkTitolo lavoro] | [Titolo lavoro] ='Nomade digitale' |+--------------------+---------------+--- ----------------------------+

Quindi, tra i due vincoli che sono stati violati, sembra che chkJobTitle è l'unico abilitato.

Possiamo verificarlo ulteriormente con la seguente query:

SELECT name, is_disabledFROM sys.check_constraintsWHERE name ='chkValidEndDate' OR name ='chkJobTitle';

Risultato:

+-----------------+---------------+| nome | is_disabled ||-----------------+---------------|| chkTitolo lavoro | 0 || chkValidEndDate | 1 |+-----------------+---------------+

Esempio 4 – Verifica solo i vincoli per una determinata tabella

Puoi aggiungere il nome di una tabella tra parentesi se vuoi solo controllare i vincoli per quella tabella:

USE Test;DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;

Risultato:

+--------------------------------------+------+- -------------------------------------------------- ------+| tavola | vincolo | Dove ||-------------------------+--------------------+-- -------------------------------------------------- -----|| [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2020-01-01' AND [EndDate] ='1999-01-01' || [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2021-10-25' AND [EndDate] ='2021-10-24' |+-----------------------+ -------------------+----------------- ----------------------------+

Esempio 5:verifica di un singolo vincolo

Puoi controllare un singolo vincolo racchiudendo il suo nome tra parentesi:

USE Test;DBCC CHECKCONSTRAINTS(chkValidEndDate);

Risultato:

+--------------------------------------+------+- -------------------------------------------------- ------+| tavola | vincolo | Dove ||-------------------------+--------------------+-- -------------------------------------------------- -----|| [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2020-01-01' AND [EndDate] ='1999-01-01' || [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2021-10-25' AND [EndDate] ='2021-10-24' |+-----------------------+ -------------------+----------------- ----------------------------+

Quando specifichi un singolo vincolo, il WITH ALL_CONSTRAINTS non ha effetto:

USE Test;DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;

Risultato:

+--------------------------------------+------+- -------------------------------------------------- ------+| tavola | vincolo | Dove ||-------------------------+--------------------+-- -------------------------------------------------- -----|| [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2020-01-01' AND [EndDate] ='1999-01-01' || [dbo].[Test Vincolo] | [chkValidEndDate] | [StartDate] ='2021-10-25' AND [EndDate] ='2021-10-24' |+-----------------------+ -------------------+----------------- ----------------------------+