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

Come abilitare un vincolo di chiave esterna in SQL Server (esempi T-SQL)

Se hai un vincolo di chiave esterna in SQL Server che è attualmente disabilitato, puoi utilizzare il codice seguente per riattivarlo.

Quando si abilita un vincolo di chiave esterna, è possibile specificare se controllare o meno i dati esistenti nella tabella. Questo vale anche quando abiliti un CHECK vincolo.

Di seguito sono riportati esempi di codice per abilitare un vincolo di chiave esterna, specificando ciascuna di queste diverse opzioni.

Esempio 1:abilitare un vincolo utilizzando WITH CHECK

Questo è il metodo consigliato (a meno che tu non abbia un motivo specifico per non usarlo).

Ecco un esempio di abilitazione di un vincolo di chiave esterna chiamato FK_Albums_Artists :

ALTER TABLE Albums 
WITH CHECK CHECK CONSTRAINT FK_Albums_Artists; 

Qui dichiaro esplicitamente WITH CHECK , che indica a SQL Server di controllare i dati esistenti prima di abilitare il vincolo. Se qualche dato viola il vincolo, il vincolo non verrà abilitato e riceverai un errore.

Questo è positivo, perché rafforza l'integrità referenziale.

Quando crei un nuovo vincolo di chiave esterna, questa è l'impostazione predefinita. Tuttavia, quando abiliti un vincolo esistente (come stiamo facendo qui), non lo è l'impostazione predefinita.

Esempio 2:abilitare un vincolo utilizzando WITH NOCHECK

In questo esempio il vincolo è abilitato senza controllare i dati esistenti:

ALTER TABLE Albums 
WITH NOCHECK CHECK CONSTRAINT FK_Albums_Artists;

Qui dichiaro esplicitamente WITH NOCHECK , che indica a SQL Server di non controllare i dati esistenti. Ciò significa che il vincolo sarà abilitato anche se la tabella contiene già dati che violano il vincolo.

Questa è l'impostazione predefinita quando si abilita un vincolo (ma non durante la creazione).

Uno dei pochi motivi (probabilmente l'unico motivo) per utilizzare questo è se si desidera mantenere dati non validi nel database. Forse hai un'eccezione una tantum in cui devi inserire una riga o più di dati non validi, ma hai bisogno che tutti i dati futuri siano conformi al vincolo.

Tuttavia, ci sono ancora dei rischi associati a questa operazione. Ecco cosa ha da dire Microsoft al riguardo:

Non consigliamo di farlo, tranne in rari casi. Il nuovo vincolo viene valutato in tutti gli aggiornamenti dei dati successivi. Eventuali violazioni dei vincoli soppresse da WITH NOCHECK quando viene aggiunto il vincolo potrebbe causare il fallimento degli aggiornamenti futuri se aggiornano le righe con dati che non seguono il vincolo.

Quindi usando WITH NOCHECK potrebbe causare problemi in seguito.

Esempio 3:abilitare un vincolo utilizzando l'opzione predefinita

Ecco un esempio che utilizza l'opzione predefinita:

ALTER TABLE Albums 
CHECK CONSTRAINT FK_Albums_Artists;

Questo esempio è l'equivalente dell'esempio precedente. Poiché non ho specificato se controllare o meno, SQL Server presume che io voglia WITH NOCHECK .

Quindi assicurati di specificare esplicitamente WITH CHECK se vuoi evitare problemi di integrità referenziale.

L'uso di CON NOCHECK rimuove la fiducia

Quando abiliti un vincolo usando (l'impostazione predefinita) WITH NOCHECK , una conseguenza di cui dovresti essere a conoscenza è che SQL Server non riterrà più attendibile tale vincolo. Lo contrassegna come non attendibile. In realtà, è già contrassegnato come non attendibile quando disabiliti il ​​vincolo.

SQL Server ha un is_not_trusted segnala che è impostato su 1 quando disabiliti un vincolo di chiave esterna (il che significa che non è attendibile) e l'unico modo per impostarlo su 0 (attendibile) è specificare WITH CHECK quando si riattiva il vincolo. D'altra parte, usando WITH NOCHECK lo abilita senza controllare i dati esistenti.

Usando WITH CHECK , assicurati che il vincolo controlli tutti i dati esistenti prima di essere abilitato. L'unico modo in cui può essere abilitato è se tutti i dati esistenti sono conformi al vincolo. Dopo aver verificato tutti i dati esistenti, il vincolo può essere considerato attendibile.

Esempio 4:verifica dello stato di fiducia/disabilitato

Puoi controllare lo stato attendibile e disabilitato interrogando sys.foreign_keys vista di sistema.

In questo modo:

SELECT 
  name AS 'Constraint',
  is_disabled,
  is_not_trusted
FROM sys.foreign_keys;

Risultato:

+-------------------+---------------+------------------+
| Constraint        | is_disabled   | is_not_trusted   |
|-------------------+---------------+------------------|
| FK_Albums_Artists | 0             | 1                |
| FK_Albums_Genres  | 0             | 0                |
+-------------------+---------------+------------------+

Questo mi dice che il vincolo che ho abilitato nell'esempio precedente ( FK_Albums_Artists ) non è attendibile.

Questo perché l'ho abilitato utilizzando l'impostazione predefinita, che è WITH NOCHECK .

Se lo riabilito usando WITH CHECK , ecco cosa succede:

ALTER TABLE Albums 
WITH CHECK CHECK CONSTRAINT FK_Albums_Artists;

SELECT 
  name AS 'Constraint',
  is_disabled,
  is_not_trusted
FROM sys.foreign_keys;

Risultato:

+-------------------+---------------+------------------+
| Constraint        | is_disabled   | is_not_trusted   |
|-------------------+---------------+------------------|
| FK_Albums_Artists | 0             | 0                |
| FK_Albums_Genres  | 0             | 0                |
+-------------------+---------------+------------------+

Fortunatamente in questo caso non avevo dati che violassero il vincolo, quindi il vincolo è stato abilitato con successo e la sua attendibilità è stata ripristinata.

Se ci fossero dati che violavano il vincolo, sarebbe stato visualizzato un errore e sarei stato costretto a correggere i dati prima di poter ripristinare la fiducia nel vincolo.