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

Come ripristinare l'attendibilità in un vincolo di chiave esterna in SQL Server (esempi T-SQL)

In SQL Server, un vincolo di chiave esterna (e un CHECK vincolo) può essere attendibile o non attendibile.

Quando un vincolo è attendibile, significa che il vincolo è stato verificato dal sistema. Quando non è attendibile, il vincolo non stato verificato dal sistema.

Fondamentalmente, quando hai un vincolo non attendibile, potresti anche avere dati non validi nel tuo database. Con questo intendo dire che potresti avere dati che violano il vincolo.

Ciò significa che non stai più mantenendo l'integrità referenziale all'interno delle tue relazioni, il che normalmente non è una buona pratica quando ti occupi di un database relazionale in produzione.

In questo articolo controllerò i miei vincoli esistenti per la loro "affidabilità" e poi li aggiornerò per renderli nuovamente affidabili.

Esempio 1 – Esaminare i vincoli esistenti

Puoi scoprire se un vincolo è attendibile o meno eseguendo una query su 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 | 1             | 1                |
| FK_Albums_Genres  | 0             | 1                |
+-------------------+---------------+------------------+

OK, quindi questo mi dice che ho due vincoli di chiave esterna ed entrambi non sono attendibili.

Uno dei vincoli è disabilitato, quindi ha senso che non sia attendibile (i dati errati possono entrare nel database ogni volta che il vincolo è disabilitato).

Ma l'altro vincolo è abilitato, quindi non dovrebbe essere inaffidabile. Non essere attendibile significa che potrebbero esserci dati non validi nel database. Non significa che ci sia dati non validi, solo che potrebbe essere.

Fondamentalmente, essendo abilitato, controllerà i dati futuri, ma non può garantire i dati esistenti. Se un vincolo è attendibile, puoi essere certo che tutti i dati esistenti sono validi.

Restituisci solo vincoli non attendibili

Potresti preferire usare un WHERE clausola per restituire solo i vincoli non attendibili. In questo modo:

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

Risultato:

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

Quindi in questo caso il risultato è lo stesso (perché tutti i vincoli attuali non sono attendibili).

Esempio 2:ripristino della fiducia

Per ripristinare l'attendibilità del tuo vincolo abilitato, riattivalo semplicemente mentre usi il WITH CHECK opzione.

In questo modo:

ALTER TABLE Albums 
WITH CHECK CHECK CONSTRAINT FK_Albums_Genres;

Ora quando interroghiamo sys.foreign_keys otteniamo un risultato diverso:

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

Risultato:

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

Possiamo vedere che il vincolo è ora attendibile, perché is_not_trusted flag è impostato su 0 .

Esempio 3 – In che modo il vincolo è diventato non attendibile?

Quando si disabilita un vincolo di chiave esterna, diventa automaticamente non attendibile. Quando riabiliti lo stesso vincolo, hai l'opportunità di ripristinarne la fiducia. Se non lo fai, rimarrà non attendibile.

Quando abiliti un vincolo di chiave esterna, hai la possibilità di specificare WITH CHECK o WITH NOCHECK . Se specifichi il successivo, il tuo vincolo rimarrà non attendibile una volta abilitato.

È importante notare che WITH NOCHECK è l'opzione predefinita, quindi se non specifichi esplicitamente che dovrebbe essere attendibile, il vincolo verrà abilitato come non attendibile.

Tuttavia, è l'opposto quando crei un vincolo di chiave esterna. Quando crei il vincolo per la prima volta, l'opzione predefinita è WITH CHECK . Quindi, se ometti questa impostazione, sarà considerata attendibile per impostazione predefinita (a meno che tu non abbia dati non validi, nel qual caso non sarà abilitato). Tuttavia, puoi ignorare questa impostazione specificando esplicitamente WITH NOCHECK quando crei il vincolo.

Per dimostrare come i tuoi vincoli abilitati possono rimanere facilmente non attendibili, riattiverò l'altra chiave (quella disabilitata), ma utilizzerò l'impostazione predefinita:

ALTER TABLE Albums 
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             | 1                |
| FK_Albums_Genres  | 0             | 0                |
+-------------------+---------------+------------------+

Quindi essendo pigro (o smemorato) e non specificando esplicitamente WITH CHECK , sono riuscito ad abilitare un vincolo mantenendo intatto il suo stato "non attendibile".

Il punto chiave di questo è:se vuoi che i tuoi vincoli riabilitati siano affidabili, dovresti sempre abilitarli usando WITH CHECK .