Mysql
 sql >> Database >  >> RDS >> Mysql

Chiavi esterne MySQL

Le chiavi esterne sono parte integrante della creazione di una relazione nei database relazionali. Ecco perché e come crearli.

Quindi abbiamo stabilito che una chiave primaria fornisce un identificatore univoco per la tabella. Ma le chiavi primarie non sono l'unico tipo di "chiave". Il nostro database può contenere anche chiavi esterne.

Cos'è una chiave esterna?

Una chiave straniera è una colonna (o raccolta di colonne) in una tabella che identifica in modo univoco una riga di un'altra tabella. Questo definisce una relazione tra le due tabelle.

Una chiave esterna consente di incrociare i dati correlati tra le tabelle. Ciò risulta utile quando una colonna contiene dati rappresentati in un'altra tabella.

Esempio

Ecco un diagramma del nostro FruitShop database che mostra la relazione tra il Frutto tabella e le Unità tavolo.

La linea nera che collega le due tabelle indica una chiave esterna. L' UnitId campo su Frutta table è una chiave esterna per UnitId campo in Unità tavolo. Pertanto, il valore che inseriamo in Fruit.UnitId deve corrispondere a un valore in Units.UnitId . Ciò abilita Fruit.UnitId per fare riferimento ai dati nelle altre colonne per quel record (ovvero il record che ha il corrispondente UnitId ).

I dati

Quindi se la nostra Frutta la tabella contiene un record come questo:

FruitId NomeFrutta Inventario UnitId Data di inserimento Aggiornamento della data
1 Mela 10 3 27-11-2012 12:42:10 27-11-2012 12:42:10

E le nostre Unità la tabella contiene i seguenti record:

UnitId NomeUnità Data di inserimento Aggiornamento della data
1 Pezzo 30-12-2011 12:46:15 30-12-2011 12:46:15
2 Mazzo 30-12-2011 12:46:15 30-12-2011 12:46:15
3 Chilogrammo 30-12-2011 12:46:15 30-12-2011 12:46:15
4 Contenitore 30-12-2011 12:46:15 30-12-2011 12:46:15
5 Libro 30-12-2011 12:46:15 30-12-2011 12:46:15
6 Oncia 30-12-2011 12:46:15 30-12-2011 12:46:15

Puoi vedere che Fruit.UnitId il campo contiene un 3 . Ora guarda le Unità tabella per il record che contiene un 3 in UnitId campo. Puoi vedere che questo record rappresenta Kilogram . Pertanto, ora sappiamo che le mele si misurano in chilogrammi.

L'aspetto positivo dell'impostazione del database in questo modo è che non è necessario ripetere i "chilogrammi" per ogni record che utilizza quell'unità. La riduzione della duplicazione è un vantaggio fondamentale dei sistemi di gestione dei database relazionali.

Vedere tutti i record in Fruit la tabella condividerà lo stesso nome di unità (ad esempio, "Kilograms", "Container", "Bunch", ecc.), dovremmo pensarci attentamente prima di aggiungere duplicati al nostro database. Senza utilizzare una relazione di chiave esterna, potremmo semplicemente scrivere i nomi delle unità direttamente in Fruit tabella (e forse chiamare la colonna "Unit", "UnitType" o "UnitName"). Quindi ci ritroveremmo con molti record che condividono lo stesso valore per la colonna del nome dell'unità. Vedremmo "Kilogram" ripetuto più e più volte contro molti record. Vedremmo anche "Bunch" ripetuto e qualsiasi altro tipo di unità popolare.

Sebbene non sia necessariamente "sbagliato" fare ciò, generalmente è più efficiente memorizzare un record per ciascuno di quei nomi di unità in una tabella separata, quindi fare riferimento a quella tabella tramite UnitId colonna. In questo modo è più efficiente che ripetere i nomi delle unità più e più volte per ogni record creato in Fruits tavolo. Inoltre, è più facile se decidiamo di aggiornare il nome di un'unità (ad esempio, cambia "Kilograms" in "Kilos"). Se aggiorniamo il nome di un'unità, ciò non influirà su Frutta tabella perché UnitId rimarrà lo stesso. Inoltre, aiuta anche a prevenire la comparsa di dati incoerenti nel nostro database.

Vincolo di chiave straniera

Un vincolo di chiave esterna è un oggetto di database che aiuta a mantenere coerenti i dati della chiave esterna. Si crea un vincolo di chiave esterna per mantenere l'integrità referenziale. Creando un vincolo di chiave esterna, stai dicendo a MySQL di applicare determinate regole sui dati. Quando i dati vengono inseriti, eliminati o aggiornati, MySQL verificherà che aderiscano alla chiave esterna che hai creato tra le tabelle. In caso contrario, impedirà la scrittura/sovrascrittura/cancellazione dei dati, mantenendo così l'integrità referenziale.

Ad esempio, se un utente tenta di inserire un valore UnitId in Fruit.UnitId colonna ma non esiste un record corrispondente in Units.UnitId colonna, quindi MySQL impedirà all'utente di inserire quel valore.

Quando abbiamo creato le nostre due tabelle, abbiamo aggiunto un vincolo di chiave esterna a Fruit tavolo. Ecco il codice che abbiamo usato per creare il vincolo:

CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE

Quando espandi i nodi in SCHEMAS a sinistra tab, puoi vedere la chiave esterna che abbiamo creato (così come le chiavi primarie):

Se provi a inserire dati che non sono conformi al vincolo di chiave esterna, dovresti ricevere un errore.

Ad esempio, se tento di inserire un record in Fruit tabella utilizzando un UnitId valore che non esiste nelle Unità tabella, ricevo il seguente errore:

Ciò si verifica perché sto cercando di inserire un valore di 5 nell' UnitId colonna quando non esiste un valore corrispondente in Units.UnitId campo.

Affinché ciò riesca, dovrei assicurarmi che ci sia un record nelle Unità tabella con un UnitId di 5 .

Chiave estera non funzionante?

Potresti incontrare la situazione occasionale in cui una chiave esterna non sembra funzionare. Ad esempio, puoi inserire correttamente i dati in una tabella anche se è presente una chiave esterna che dovrebbe impedire l'inserimento di tali dati.

Ci sono alcune cose che puoi controllare in questa situazione.

  • Assicurati di aver aggiunto ON DELETE e ON UPDATE clausole nel tuo codice. Ad esempio, ON DELETE RESTRICT ON UPDATE CASCADE . Consulta il nostro esempio CREATE TABLE per sapere quando inserire questo codice.
  • Assicurati che la tabella sia InnoDB . Puoi farlo aggiungendo ENGINE=InnoDB alla fine del tuo CREATE TABLE istruzione (vedi il mio esempio di quando abbiamo creato le nostre tabelle). Alcuni motori (come MyISAM ) non supportano i vincoli di chiave esterna, ma non forniscono alcun avviso al riguardo quando si tenta di creare il proprio vincolo di chiave esterna. Se il tuo motore predefinito non è InnoDB allora è probabile che le tue chiavi esterne non siano supportate.
  • Assicurati che MySQL stia effettivamente controllando le chiavi esterne. Puoi farlo eseguendo il seguente codice:SET FOREIGN_KEY_CHECKS=1 .

Disabilita il controllo della chiave esterna

Potrebbero esserci momenti in cui i vincoli di chiave esterna possono diventare inutilmente restrittivi, al punto da ostacolare gravemente i tuoi sforzi nel caricamento dei dati. Ad esempio, quando hai appena creato un database e devi caricare i dati iniziali. O se hai bisogno di eliminare un gruppo di tabelle e ricaricare i dati.

Se non carichi i dati nell'ordine corretto, probabilmente continuerai a ricevere errori di chiave esterna a causa del caricamento dei dati nell'ordine sbagliato (ovvero stai tentando di caricare le tabelle figlio prima che le tabelle padre abbiano avuto il loro dati caricati).

Questo non è solo un problema durante il caricamento i dati. Potresti anche riscontrare questo problema durante la creazione del database in primo luogo. Se non crei le tabelle nell'ordine corretto, potresti riscontrare errori dovuti a vincoli di chiave esterna.

Se non si conosce l'ordine padre-figlio corretto, potrebbe essere necessario molto tempo e fatica per stabilire l'ordine corretto per creare il database o caricare i dati. In casi come questi, sarebbe meglio dire temporaneamente a MySQL di non controllare le chiavi esterne per ora.

Puoi disabilitare il controllo della chiave esterna con il seguente codice:

FOREIGN_KEY_CHECKS=0

Per abilitarlo di nuovo, procedere come segue:

FOREIGN_KEY_CHECKS=1