mysql Il vincolo di chiave esterna è un errore formato in modo errato


173

Ho due tabelle, table1è la tabella padre con una colonna IDe table2con una colonna IDFromTable1(non il nome reale) quando ho messo un FK IDFromTable1a IDnella table1ottengo l'errore Foreign key constraint is incorrectly formed error. Vorrei eliminare il record della tabella 2 se il table1record viene eliminato. Grazie per qualsiasi aiuto

ALTER TABLE `table2`  
   ADD CONSTRAINT `FK1` 
      FOREIGN KEY (`IDFromTable1`) REFERENCES `table1` (`ID`) 
      ON UPDATE CASCADE 
      ON DELETE CASCADE;

Fammi sapere se sono necessarie altre informazioni. Sono nuovo di mysql


4
Quale motore stai usando per i tuoi tavoli? Di che tipo è table2.IDFromTable1e table1.ID?
Romain,

5
Inoltre, controlla che i set di caratteri per entrambe le tabelle siano uguali.
Carsten,

Entrambi i motori delle tabelle sono innoDB. non sono sicuro di dove trovare i set di caratteri e entrambi sono di tipo char. L'ID è la chiave primaria nella
tabella 1

2
Fornisci le definizioni di tabella per table1 e table2. Come hai ricevuto questo errore? Usi uno strumento per creare la chiave esterna? Sembra che non sia un errore nativo di MySQL.
Devart,

@ user516883 - Hai bisogno di aiuto per ottenere le definizioni delle tabelle? In HeidiSQL puoi semplicemente fare clic sulla scheda CREATE code .
Álvaro González l'

Risposte:


422

Ho riscontrato questo stesso problema con HeidiSQL. L'errore che ricevi è molto criptico. Il mio problema finì per essere che la colonna chiave esterna e la colonna di riferimento non erano dello stesso tipo o lunghezza.

La colonna chiave esterna era SMALLINT(5) UNSIGNEDe la colonna referenziata era INT(10) UNSIGNED. Una volta che ho creato entrambi lo stesso tipo esatto, la creazione della chiave esterna ha funzionato perfettamente.


58
O potrebbe essere che la colonna di riferimento non sia una chiave primaria
nawfal,

9
Un problema simile per me - la tabella di riferimento non esisteva ancora. Ops.
Amalgovinus,

5
Ho sperimentato totalmente quello che ha fatto Jake, ma ho riscontrato un altro problema FK (tipo diverso) su HeidiSQL. FK su varchar deve essere la stessa raccolta. Spero che possa aiutare qualcun altro in futuro!
cbloss793,

10
Nel mio caso è stato a causa di diverse codifiche e regole di confronto.
Khatri,

1
@nawfal - Credo che non debba necessariamente essere una chiave primaria, ma DEVE avere un indice. Le chiavi primarie vengono automaticamente indicizzate.
Itai,

48

Ho avuto lo stesso problema quando la tabella padre è stata creata utilizzando il MyISAMmotore. È un errore sciocco, che ho risolto con:

ALTER TABLE parent_table ENGINE=InnoDB;

Grazie mille, stavo impazzendo con questo. Qualche idea sul perché il database cambierebbe improvvisamente il motore per le tabelle?
Robert Franklin,

28

assicurarsi che le colonne siano identiche (dello stesso tipo) e, in caso contrario primary_key, assicurarsi che lo sia INDEXED.


Mi è anche successo che non ci sono stati errori, ma la chiave esterna non è stata aggiunta (1 era e 1 non era effettivamente), ma dopo l'aggiunta semplice KEY referencing_column(referencing_column) PRIMA di entrambe le definizioni delle chiavi esterne sono state entrambe aggiunte correttamente :)
jave.web

2
Le chiavi che non venivano indicizzate erano il mio problema.
Neil Masters,

1
Ho avuto questo problema e il problema era che avevo una chiave primaria a doppia colonna e non è possibile utilizzare la seconda colonna della chiave primaria come chiave esterna. Quindi ho appena aggiunto il proprio indice per la seconda colonna della chiave primaria e poi ha funzionato.
Firze,

21

La sintassi per la definizione di chiavi esterne è molto tollerante, ma per chiunque sia inciampato su questo, il fatto che le chiavi esterne debbano essere "dello stesso tipo" si applica anche alle regole di confronto, non solo al tipo di dati, alla lunghezza e alla firma dei bit.

Non che avresti mescolato le regole di confronto nel tuo modello (vero?), Ma se lo fai, assicurati che i tuoi campi chiave primaria ed esterna siano dello stesso tipo di regole di confronto in phpmyadmin o Heidi SQL o qualunque cosa tu usi.

Spero che questo ti risparmi le quattro ore di prova ed errore che mi è costato.


1
Grazie! Risulta che il mio host online utilizza il motore ISAM e per gli sviluppatori locali utilizzo InnoDB. Quando ho eseguito il backup di un tavolo dall'host al boom locale.
Ben

Le versioni recenti di MariaDB sembrano usare utf8_mb4 come set di caratteri predefinito (quando non impostato esplicitamente nella configurazione del server), così COLLATE utf8mb4_unicode_cicome il mio (imprevisto) problema (sulla macchina dev).
JonnyJD,

13

Ho avuto lo stesso problema, ma l'ho risolto.

Assicurati solo che la colonna 'ID' in 'tabella1' abbia un indice UNICO !

E ovviamente il tipo, la lunghezza delle colonne 'ID' e 'IDFromTable1' in queste due tabelle deve essere la stessa. Ma tu lo sai già.


Mi hai reso felice.
kevenlolo,

1
Felice di aiutare! ;)
Renat Gatin,

Non sono sicuro dei dettagli, ma ho avuto una chiave composita con questo errore che è stato corretto aggiungendo singoli indici univoci per le colonne.
Halvor Holsten Strand,

La colonna referenziata deve essere indicizzata, non deve essere unica (anche se questo è il solito caso).
Barmar,

10

Solo per completamento.

Questo errore potrebbe verificarsi anche se si dispone di una chiave esterna con VARCHAR (..) e il set di caratteri della tabella di riferimento è diverso dalla tabella a cui fa riferimento.

ad es. VARCHAR (50) in una tabella Latin1 è diversa da VARCHAR (50) in una tabella UTF8.


1
Anche utf8_unicode_ci e utf8_general_ci stanno causando l'errore
leuchtdiode

10

i testi di errore mysql non aiutano molto, nel mio caso, la colonna aveva un vincolo "non null", quindi il "on delete set null" non era permesso


7

se tutto va bene, basta aggiungere ->unsigned();alla fine di foregin key.

se non funziona, controllare il tipo di dati di entrambi i campi. devono essere uguali.


5

Ho avuto lo stesso problema, entrambe le colonne erano INT (11) NON NULL ma non riuscivo a creare la chiave esterna. Ho dovuto disabilitare i controlli delle chiavi esterne per eseguirlo correttamente:

SET FOREIGN_KEY_CHECKS=OFF;
ALTER TABLE ... ADD CONSTRAINT ...
SET FOREIGN_KEY_CHECKS=ON;

Spero che questo aiuti qualcuno.


4
In realtà è FOREIGN_KEY_CHECKS
Xmanoux il

Questo mi ha aiutato a passare oltre, ma il mio problema mancava l'indice primmary nella colonna
bumerang

4

Un'altra probabile causa per la visualizzazione di questo errore. L'ordine in cui stavo creando le tabelle era sbagliato. Stavo cercando di fare riferimento a una chiave da una tabella non ancora creata.


4

(Ultimo rinvio) Anche se il nome del campo e il tipo di dati sono gli stessi, ma le regole di confronto non sono uguali, si verificherà anche quel problema.

Per esempio

    NOME TBL | TIPO DI DATI | COLLATION        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         utf8_general_ci

Prova a cambiarlo in

    NOME TBL | TIPO DI DATI | COLLATION        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         latin1_general_ci

....

Questo ha funzionato per me.


3

Controlla il motore dei tavoli, entrambi i tavoli devono essere lo stesso motore, che mi ha aiutato così tanto.


Buon punto! Ho a che fare con un database Zen Cart in MySQL le cui tabelle sono tutte predefinite nel motore MyISAM. Ho aggiunto una tabella usando il motore InnoDB e ho provato ad aggiungere un vincolo di chiave esterna dalla mia tabella al carrello Zen Cart uno. Ha fallito con questo oscuro errore "erroneamente formato". Puoi vedere il motore di ogni tavolo conSHOW TABLE STATUS LIKE 'table_name';
Neek

2

Ho avuto gli stessi problemi.

Il problema è che la colonna di riferimento non è una chiave primaria.

Rendilo una chiave primaria e il problema è risolto.


Non deve essere un PK, può anche essere UNICO NON NULL.
Philipxy,

In realtà ... nel mio caso è sufficiente impostarlo su un tipo di indice normalmente funzionante.
hendr1x,

2

Sebbene le altre risposte siano piuttosto utili, volevo solo condividere anche la mia esperienza.

Ho affrontato il problema quando avevo eliminato una tabella di cui si idfaceva già riferimento come chiave esterna in altre tabelle ( con dati ) e provato a ricreare / importare la tabella con alcune colonne aggiuntive.

La query per la ricreazione (generata in phpMyAdmin) era simile alla seguente:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL,            /* No PRIMARY KEY index */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

... /* SOME DATA DUMP OPERATION */

ALTER TABLE `the_table`
  ADD PRIMARY KEY (`id`), /* PRIMARY KEY INDEX */
  ADD UNIQUE KEY `uk_acu_donor_name` (`name`);

Come puoi notare, l' PRIMARY KEYindice è stato impostato dopo la creazione ( e l'inserimento dei dati ) che causava il problema.

Soluzione

La soluzione consisteva nell'aggiungere l' PRIMARY KEYindice nella query di definizione della tabella per la idquale veniva indicato come chiave esterna, rimuovendolo anche dalla ALTER TABLEparte in cui venivano impostati gli indici:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL PRIMARY KEY,            /* <<== PRIMARY KEY INDEX ON CREATION */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Ha funzionato per me. Ero preoccupato di dover reinstallare il mio software;)
Dewlance

2

Ho perso per ore per quello!

PK in un tavolo era utf8nell'altro era utf8_unicode_ci!


1

Prova a correre come segue:

mostra crea tabella Parent

// e controlla se il tipo per entrambe le tabelle è lo stesso, come myISAM o innoDB, ecc
// Altri aspetti da verificare con questo messaggio di errore: le colonne utilizzate come esterne 
le chiavi devono essere indicizzate, devono essere dello stesso tipo 
(se cioè uno è di tipo smallint (5) e l'altro di tipo smallint (6), 
non funzionerà) e, se sono numeri interi, dovrebbero essere senza segno.

// o verifica la presenza di set di caratteri
mostra variabili come "character_set_database";
mostra variabili come "collation_database";

// modificato: prova qualcosa del genere
Tabella ALTER TABLE2
AGGIUNGI VINCITORE fk_IdTable2
TASTO ESTERO (Table1_Id)
RIFERIMENTI Tabella1 (Tabella1_Id)
IN AGGIORNAMENTO CASCADE 
A CANCELLARE CASCATA;

9
Prova a eseguire SHOW ENGINE INNODB STATUS per ottenere ulteriori dettagli sull'errore
Sudhir Bastakoti,

@SudhirBastakoti - +1! Che ha fatto per me. I dettagli sono utili È stato in grado di risolvere rapidamente il problema.
Paul Carlton,

1

Ho avuto lo stesso problema con Symfony 2.8.

All'inizio non l'ho capito, perché non c'erano problemi simili con la lunghezza int delle chiavi esterne ecc.

Alla fine ho dovuto fare quanto segue nella cartella del progetto. (Un riavvio del server non ha aiutato!)

app/console doctrine:cache:clear-metadata app/console doctrine:cache:clear-query app/console doctrine:cache:clear-result


1

grazie S Doerin:

"Solo per completamento. Questo errore potrebbe valere anche se si dispone di una chiave esterna con VARCHAR (..) e il set di caratteri della tabella referenziata è diverso dalla tabella a cui fa riferimento. Ad es. VARCHAR (50) in una tabella Latin1 è diverso da VARCHAR (50) in una tabella UTF8. "

ho risolto questo problema, cambiando il tipo di caratteri della tabella. la creazione ha latin1 e il corretto è utf8.

aggiungi la riga successiva. SET DI CARATTERI PREDEFINITO = utf8;


1

Ho avuto problemi con l'utilizzo della tabella Alter per aggiungere una chiave esterna tra due tabelle e la cosa che mi ha aiutato era assicurarmi che ogni colonna a cui stavo cercando di aggiungere una relazione di chiave esterna fosse indicizzata. Per fare ciò in PHP myAdmin: vai alla tabella e fai clic sulla scheda struttura. Fare clic sull'opzione di indice per indicizzare la colonna desiderata come mostrato nello screenshot:

inserisci qui la descrizione dell'immagine

Dopo aver indicizzato entrambe le colonne, stavo cercando di fare riferimento alle mie chiavi esterne, sono stato in grado di utilizzare correttamente la tabella alter e creare la relazione di chiave esterna. Vedrai che le colonne sono indicizzate come nello screenshot qui sotto:

inserisci qui la descrizione dell'immagine

nota come zip_code appare in entrambe le tabelle.


1

È necessario verificare che entrambi siano uguali in tutte le sue proprietà, incluso in "Fascicolazione"


1

Stavo usando HeidiSQL e per risolvere questo problema ho dovuto creare un indice nella tabella referenziata con tutte le colonne referenziate.

aggiungendo indice alla tabella Heidisql


Lo stesso per me in mysql: InnoDB richiede indici su chiavi esterne e chiavi di riferimento in modo che i controlli delle chiavi esterne possano essere veloci e non richiedere una scansione della tabella.
hendr1x,

1

Ho riscontrato lo stesso problema proprio ora. Nel mio caso, tutto quello che dovevo fare è assicurarmi che la tabella a cui mi riferisco nella chiave esterna debba essere creata prima della tabella corrente (precedentemente nel codice). Pertanto, se si fa riferimento a una variabile (x * 5), il sistema dovrebbe sapere cos'è x (x deve essere dichiarato nelle precedenti righe di codice). Questo ha risolto il mio problema, spero che possa aiutare qualcun altro.


Ho avuto lo stesso problema in MariaDB v10.3.18. Abbiamo usato MySQL in precedenza e avvisava che una chiave esterna indicava una tabella inesistente.
MarthyM il

0

Ho avuto lo stesso problema con Laravel 5.1 Migration Schema Builder con MariaDB 10.1.

Il problema era che avevo digitato unignedinvece di unsigned(ils mancava lettera) durante l'impostazione della colonna.

Dopo aver corretto l'errore di battitura è stato corretto per me.


0

Anche io ho riscontrato lo stesso problema con mysql e liquibase. Quindi questo è il problema: la tabella da cui si desidera fare riferimento a una colonna di un'altra tabella è diversa nel caso del tipo di dati o in termini di dimensioni del tipo di dati.

Error appears in below scenario:
Scenario 1:
Table A has column id, type=bigint
Table B column referenced_id type varchar(this column gets the value from the id column of Table A.)
Liquibase changeset for table B:

    <changeset id="XXXXXXXXXXX-1" author="xyz">
            <column name="referenced_id" **type="varchar"**>
        </column>
            </changeset>
    <changeSet id="XXXXXXXXXXX-2" author="xyz">
                <addForeignKeyConstraint constraintName="FK_table_A"
                    referencedTableName="A" **baseColumnNames="referenced_id**"
                    referencedColumnNames="id" baseTableName="B" />
    </changeSet>

Table A changeSet:

    <changeSet id="YYYYYYYYYY" author="xyz">
     <column **name="id"** **type="bigint"** autoIncrement="${autoIncrement}">
                    <constraints primaryKey="true" nullable="false"/>
                </column>
    </changeSet>

Solution: 
correct the type of table B to bigint because the referenced table has type bigint.

Scenrario 2:
The type might be correct but the size might not.
e.g. :
Table B : referenced column type="varchar 50"
Table A : base column type ="varchar 255"

Solution change the size of referenced column to that of base table's column size.

0

Verificare di aver specificato il nome della tabella nel caso corretto (se i nomi delle tabelle fanno distinzione tra maiuscole e minuscole nel database). Nel mio caso ho dovuto cambiare

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

per

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `CUSTOMER` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

nota il customercambiato in CUSTOMER.


0

Oppure puoi usare DBDesigner4 che ha un'interfaccia grafica per creare il tuo database e collegarlo usando FK. Fare clic con il tasto destro del mouse sulla tabella e selezionare "Copia tabella SQL Create" che crea il codice.

inserisci qui la descrizione dell'immagine


0

È un argomento vecchio ma ho scoperto qualcosa. Durante la creazione di un banco di lavoro MySQL, ottiene anche le relazioni dell'altra tabella. lascia semplicemente i pilastri a cui ti riferisci. Cancella altre colonne aggiunte automaticamente. Questo funziona per me.


0

Il mio caso era che avevo un refuso sulla colonna di riferimento:

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( coutry_code );
ERROR 1005 (HY000): Can't create table `blog`.`t_user` (errno: 150 "Foreign key constraint is incorrectly formed")

Il messaggio di errore è piuttosto enigmatico e ho provato di tutto, verificando i tipi di colonne, regole di confronto, motori, ecc.

Mi ci è voluto un po 'di tempo per annotare l'errore di battitura e dopo aver risolto tutto ha funzionato bene:

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( country_code );
Query OK, 2 rows affected (0.039 sec)              
Records: 2  Duplicates: 0  Warnings: 0

0

Devo affrontare questo problema l'errore si è verificato quando si inserisce la chiave primaria in diversi tipi di dati come:

Tabella 1:

 Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('product_name');
        });

Tavolo 2:

Schema::create('brands', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('brand_name');
        });

il tipo di dati per l'id della seconda tabella deve essere incrementi


0

Il problema è molto semplice da risolvere

es: hai due tabelle con nomi utenti e post e vuoi creare una chiave esterna nella tabella post e tu usi phpMyAdmin

1) nella tabella di posta aggiungi una nuova colonna ( nome : use_id | tipo : come l' id nella tabella utente | Lunghezza : come l' id nella tabella utente | Predefinito : NULL | Attributi : unsigned | index: INDEX)

2) nella scheda Struttura vai alla vista relazioni ( Nome vincolo : auto impostato da phpmyAdmin | nome colonna : seleziona id_utente | tabella : utenti | chiave : id, ...)

È stato semplicemente risolto

javad mosavi iran / urmia

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.