Domanda

Sto imparando lentamente SQL nelle ultime settimane. Ho raccolto tutta l'algebra relazionale e le basi di come funzionano i database relazionali. Quello che sto cercando di fare ora è imparare come è implementato.

Un ostacolo in cui mi sono imbattuto in questo, sono le chiavi esterne in MySQL. Non riesco a trovare molto sull'altro oltre a quello che esiste nello schema di archiviazione InnoDB che MySQL ha.

Qual è un semplice esempio di chiavi esterne implementate in MySQL?

Ecco una parte di uno schema che ho scritto che non sembra funzionare se preferisci sottolineare il mio difetto piuttosto che mostrarmi un esempio funzionante.

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories,
Foreign Key(`uID`) references users
) ENGINE=InnoDB;
È stato utile?

Soluzione

Supponendo che le tue categorie e la tabella degli utenti esistano già e contengano rispettivamente cID e uID come chiavi primarie, questo dovrebbe funzionare:

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories(`cID`),
Foreign Key(`uID`) references users(`uID`)
) ENGINE=InnoDB;

Il nome della colonna è richiesto nella clausola riferimenti .

Altri suggerimenti

Modificato: Robert e Vinko dichiarano che è necessario dichiarare il nome della colonna di riferimento nel vincolo di chiave esterna. Ciò è necessario in InnoDB, sebbene in SQL standard sia possibile omettere il nome della colonna di riferimento se è lo stesso nome nella tabella padre.

Un'idiosincrasia che ho riscontrato in MySQL è che la dichiarazione di chiave esterna fallirà silenziosamente in diverse circostanze:

  • L'installazione di MySQL non include il motore innodb
  • Il tuo file di configurazione MySQL non abilita il motore innodb
  • Non dichiari la tua tabella con il modificatore di tabella ENGINE = InnoDB
  • La colonna chiave esterna non è esattamente lo stesso tipo di dati della colonna chiave primaria nella tabella referenziata

Sfortunatamente, MySQL non dà alcun messaggio che non è riuscito a creare il vincolo di chiave esterna. Ignora semplicemente la richiesta e crea la tabella senza la chiave esterna (se si MOSTRANO i messaggi CREATE TABLE, è possibile che non venga visualizzata alcuna dichiarazione di chiave esterna). Ho sempre pensato che questa sia una cattiva funzionalità di MySQL!

Suggerimento: l'argomento intero per i tipi di dati interi (ad es. BIGINT (20)) non è necessario. Non ha nulla a che fare con le dimensioni o l'intervallo di archiviazione della colonna. BIGINT ha sempre le stesse dimensioni indipendentemente dall'argomento che gli dai. Il numero si riferisce a quante cifre MySQL riempirà la colonna se usi il modificatore di colonna ZEROFILL.

Questo ha alcuni codice che mostra come creare chiavi esterne da soli e in CREATE TABLE.

Ecco uno degli esempi più semplici da quello:

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (
    id INT, 
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id) REFERENCES parent(id)
    ON DELETE CASCADE
) ENGINE=INNODB;

Sono d'accordo con Robert. Ti manca il nome della colonna nella clausola references (e dovresti visualizzare l'errore 150). Aggiungerò che puoi verificare come le tabelle sono state create nella realtà con:

SHOW CREATE TABLE posts;

Le risposte precedenti riguardano il vincolo di chiave esterna. Mentre il vincolo di chiave esterna è sicuramente utile per mantenere l'integrità referenziale, il concetto di "chiave esterna" stesso è fondamentale per il modello relazionale di dati, indipendentemente dal fatto che si usi il vincolo o meno.

Ogni volta che fai un equijoin , stai equiparando una chiave esterna a qualcosa, di solito la chiave a cui fa riferimento. Esempio:

select *
from 
   Students
inner join
   StudentCourses
on Students.StudentId = StudentCourses.StudentId

StudentCourses.StudentId è una chiave esterna che fa riferimento a Students.StudentId.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top