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

MySQL Creazione di tabelle con chiavi esterne che danno errno:150

Ho avuto lo stesso problema con ALTER TABLE ADD FOREIGN KEY .

Dopo un'ora, ho scoperto che queste condizioni devono essere soddisfatte per non ricevere l'errore 150:

  1. La tabella Parent deve esistere prima di definire una chiave esterna a cui fare riferimento. È necessario definire le tabelle nell'ordine corretto:prima la tabella padre, quindi la tabella figlio. Se entrambe le tabelle fanno riferimento l'una all'altra, devi creare una tabella senza vincoli FK, quindi creare la seconda tabella, quindi aggiungere il vincolo FK alla prima tabella con ALTER TABLE .

  2. Le due tabelle devono supportare entrambe i vincoli di chiave esterna, ovvero ENGINE=InnoDB . Altri motori di archiviazione ignorano silenziosamente le definizioni di chiavi esterne, quindi non restituiscono errori o avvisi, ma il vincolo FK non viene salvato.

  3. Le colonne di riferimento nella tabella padre devono essere le colonne più a sinistra di una chiave. Meglio se la chiave nella Parent è PRIMARY KEY o UNIQUE KEY .

  4. La definizione FK deve fare riferimento alle colonne PK nello stesso ordine della definizione PK. Ad esempio, se l'FK REFERENCES Parent(a,b,c) quindi la PK del genitore non deve essere definita sulle colonne nell'ordine (a,c,b) .

  5. Le colonne PK nella tabella padre devono essere dello stesso tipo di dati delle colonne FK nella tabella figlio. Ad esempio, se una colonna PK nella tabella padre è UNSIGNED , assicurati di definire UNSIGNED per la colonna corrispondente nel campo Tabella figlio.

    Eccezione:la lunghezza delle stringhe potrebbe essere diversa. Ad esempio, VARCHAR(10) può fare riferimento a VARCHAR(20) o viceversa.

  6. Qualsiasi colonna FK di tipo stringa deve avere lo stesso set di caratteri e regole di confronto delle colonne PK corrispondenti.

  7. Se sono già presenti dati nella tabella Child, ogni valore nelle colonne FK deve corrispondere a un valore nelle colonne PK della tabella padre. Verifica questo con una query come:

    SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
    WHERE Parent.PK IS NULL;
    

    Questo deve restituire zero (0) valori non corrispondenti. Ovviamente, questa query è un esempio generico; devi sostituire i nomi delle tabelle e delle colonne.

  8. Né la tabella padre né la tabella figlio possono essere un TEMPORARY tabella.

  9. Né la tabella Parent né la tabella Child possono essere PARTITIONED tabella.

  10. Se dichiari un FK con il ON DELETE SET NULL opzione, le colonne FK devono essere nullable.

  11. Se si dichiara un nome di vincolo per una chiave esterna, il nome del vincolo deve essere univoco nell'intero schema, non solo nella tabella in cui è definito il vincolo. Due tabelle potrebbero non avere il proprio vincolo con lo stesso nome.

  12. Se ci sono altri FK in altre tabelle che puntano allo stesso campo per il quale stai tentando di creare il nuovo FK e sono malformati (cioè con regole di confronto diverse), dovranno prima essere resi coerenti. Questo potrebbe essere il risultato di modifiche passate in cui SET FOREIGN_KEY_CHECKS = 0; è stato utilizzato con una relazione incoerente definita per errore. Vedi la risposta di @andrewdotn di seguito per istruzioni su come identificare questi FK problematici.

Spero che questo aiuti.