In questo articolo viene illustrato come creare una chiave esterna in SQL Server utilizzando Transact-SQL. Mostro come creare una chiave esterna al momento della creazione della tabella (anziché aggiornare una tabella esistente).
Una chiave esterna è una colonna che fa riferimento alla colonna della chiave primaria di un'altra tabella. Questo crea una relazione tra le tabelle.
Esempio 1 – Preparazione
In questo esempio creerò un database di test con una tabella. Questa tabella conterrà la chiave primaria a cui farà riferimento la nostra chiave esterna.
Crea il database:
CREATE DATABASE FK_Test;
Ora crea la tabella delle chiavi primarie:
USE FK_Test; CREATE TABLE Country ( CountryId int IDENTITY (1,1) NOT NULL PRIMARY KEY, CountryName nvarchar(60) );
Esempio 2:creare la chiave esterna
Ora che abbiamo una tabella con una chiave primaria, creiamo un'altra tabella con una chiave esterna che faccia riferimento a quella chiave primaria.
CREATE TABLE City ( CityId int IDENTITY (1,1) NOT NULL PRIMARY KEY, CountryId int NOT NULL REFERENCES Country(CountryId), CityName nvarchar(60) );
Questo è il modo più semplice per creare una chiave esterna. Tutto ciò che facciamo è aggiungere i REFERENCES
clausola (insieme alla tabella e alla colonna della chiave primaria) alla colonna che avrà il vincolo di chiave esterna.
Per essere chiari, la parte che definisce la chiave esterna è questa:
REFERENCES Country(CountryId)
Questo è incluso nella definizione della colonna e indica semplicemente che questa colonna farà riferimento a CountryId
colonna nel Country
tabella.
In questo caso, sia la chiave esterna che la chiave primaria a cui fa riferimento, condividono lo stesso nome (CountryId
). Tuttavia, questo non è un requisito:la colonna della chiave esterna può avere un nome completamente diverso dalla colonna a cui fa riferimento (sebbene tutte le colonne che partecipano a una relazione di chiave esterna debbano essere definite con la stessa lunghezza e scala).
In questo esempio SQL Server genera automaticamente il nome della chiave esterna. Questo perché non ho fornito un nome. Continua a leggere per vedere come creare un nome per la tua chiave esterna.
Ma prima, controlliamo il vincolo di chiave esterna che abbiamo appena creato.
Esempio 3:verifica del vincolo di chiave esterna
Esistono molti modi per restituire una chiave esterna utilizzando T-SQL, ed eccone uno:
EXEC sp_fkeys @fktable_name = City;
Risultato (usando l'output verticale):
PKTABLE_QUALIFIER | FK_Test PKTABLE_OWNER | dbo PKTABLE_NAME | Country PKCOLUMN_NAME | CountryId FKTABLE_QUALIFIER | FK_Test FKTABLE_OWNER | dbo FKTABLE_NAME | City FKCOLUMN_NAME | CountryId KEY_SEQ | 1 UPDATE_RULE | 1 DELETE_RULE | 1 FK_NAME | FK__City__CountryId__38996AB5 PK_NAME | PK__Country__10D1609FC8BFA7F2 DEFERRABILITY | 7
I sp_fkeys
la procedura memorizzata di sistema restituisce informazioni sulla nostra chiave esterna, la chiave primaria associata e altri dettagli rilevanti. Passi semplicemente il nome della tabella della chiave esterna o della tabella della chiave primaria e restituirà le informazioni pertinenti.
In questo esempio, passo il nome della tabella della chiave esterna:City
. Nei risultati, possiamo guardare
FK_NAME
colonna per vedere che questa tabella ha un vincolo di chiave esterna chiamato
FK__City__CountryId__38996AB5
. Questo è quello che abbiamo appena creato.
Quindi, ora che abbiamo creato la chiave esterna, ogni volta che tentiamo di inserire o aggiornare un valore in City.CountryId
colonna, il vincolo di chiave esterna lo consentirà solo se lo stesso valore esiste già in Country.CountryId
colonna. Ciò garantisce che l'integrità referenziale sia mantenuta all'interno del database.
Esempio 4 – Altre opzioni
È possibile aggiungere più opzioni alla definizione della chiave esterna.
Ad esempio, puoi fornire un nome per la chiave esterna. Puoi anche specificare cosa deve accadere ai valori in questa colonna se il valore corrispondente nella chiave primaria viene aggiornato o eliminato.
Qui creo di nuovo entrambe le tabelle, ma questa volta specifico esplicitamente queste opzioni (faccio lo stesso per le chiavi primarie):
CREATE TABLE Country ( CountryId int IDENTITY (1,1) NOT NULL, CONSTRAINT PK_Country_CountryId PRIMARY KEY CLUSTERED (CountryId), CountryName nvarchar(60) ); CREATE TABLE City ( CityId int IDENTITY (1,1) NOT NULL, CONSTRAINT PK_City_CityId PRIMARY KEY CLUSTERED (CityId), CountryId int NOT NULL, CONSTRAINT FK_City_Country FOREIGN KEY (CountryID) REFERENCES Country (CountryID) ON DELETE CASCADE ON UPDATE CASCADE, CityName nvarchar(60) );
In questo caso, la definizione della chiave esterna inizia con CONSTRAINT
, seguito dal nome della chiave esterna, seguito da FOREIGN KEY
, seguito dalla colonna a cui verrà applicato il vincolo di chiave esterna (inserita tra parentesi).
Quindi vediamo gli stessi REFERENCES
clausola che abbiamo visto nell'esempio precedente.
Il ON DELETE CASCADE
e ON UPDATE CASCADE
le clausole vengono utilizzate per garantire che le modifiche apportate a Country
vengono propagate automaticamente alla City
tavolo. Ad esempio, se una riga viene eliminata dalla tabella padre (chiave primaria), tutte le righe corrispondenti vengono eliminate dalla tabella di riferimento (chiave esterna).
Il valore predefinito per ON DELETE
e ON UPDATE
è NO ACTION
. In questo caso, Motore di database genera un errore e viene eseguito il rollback dell'azione di aggiornamento o eliminazione sulla riga nella tabella padre.
Puoi anche usare SET NULL
per impostare la colonna della chiave esterna su NULL
(richiede che la colonna della chiave esterna sia nullable) o SET DEFAULT
per impostarlo sul valore predefinito (richiede che la colonna della chiave esterna abbia una definizione predefinita. Se una colonna è nullable e non è stato impostato alcun valore predefinito esplicito, NULL
diventa il valore predefinito implicito della colonna).
In questo esempio ho anche colto l'occasione per nominare le chiavi primarie. Puoi vedere che la sintassi della chiave primaria è simile alla sintassi della chiave esterna, ma senza i REFERENCES
clausola (e con aggiunta di CLUSTERED
argomento, che è l'impostazione predefinita per le chiavi primarie).
Ora controlla la chiave esterna:
EXEC sp_fkeys @fktable_name = City;
Risultato:
PKTABLE_QUALIFIER | FK_Test PKTABLE_OWNER | dbo PKTABLE_NAME | Country PKCOLUMN_NAME | CountryId FKTABLE_QUALIFIER | FK_Test FKTABLE_OWNER | dbo FKTABLE_NAME | City FKCOLUMN_NAME | CountryId KEY_SEQ | 1 UPDATE_RULE | 0 DELETE_RULE | 0 FK_NAME | FK_City_Country PK_NAME | PK_Country_CountryId DEFERRABILITY | 7
Possiamo vedere che il nome della chiave esterna è ora FK_City_Country e il vincolo di chiave primaria della colonna a cui fa riferimento è chiamato PK_Country_CountryId .
Esempio 5 – Chiave esterna su più colonne
Puoi anche creare una chiave esterna su più colonne che faccia riferimento a una chiave primaria multicolonna. Le chiavi primarie multicolonna sono anche note come chiavi primarie composite. Per creare una chiave esterna composita, separa semplicemente le colonne con una virgola durante la definizione della chiave.
In questo modo:
CONSTRAINT FK_FKName FOREIGN KEY (FKColumn1, FKColumn2) REFERENCES PrimaryKeyTable (PKColumn1, PKColumn2)
Vedere Come creare una chiave esterna composita in SQL Server per un esempio più dettagliato.
La chiave primaria è davvero necessaria?
Una chiave primaria non è assolutamente necessaria per le chiavi esterne, poiché potresti utilizzare un vincolo univoco o un indice univoco. In particolare, la documentazione Microsoft afferma questo:
FOREIGN KEY
i vincoli possono fare riferimento solo alle colonne in PRIMARY KEY
o UNIQUE
vincoli nella tabella di riferimento o in un UNIQUE INDEX
nella tabella di riferimento.
Quindi, sebbene sia generalmente buona norma avere chiavi primarie su tutte le tabelle, le tue chiavi esterne non sono obbligate a farvi riferimento.