mysql Fremdschlüsseleinschränkung ist falsch geformter Fehler


173

Ich habe zwei Tabellen, table1ist die übergeordnete Tabelle mit einer Spalte IDund table2mit einer Säule IDFromTable1(nicht der tatsächliche Name) , wenn ich ein FK legte IDFromTable1um IDin table1ich den Fehler Foreign key constraint is incorrectly formed error. Ich möchte den Datensatz in Tabelle 2 löschen, wenn der table1Datensatz gelöscht wird. Vielen Dank für jede Hilfe

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

Lassen Sie mich wissen, wenn weitere Informationen benötigt werden. Ich bin neu in MySQL


4
Welche Engine verwenden Sie für Ihre Tische? Was ist die Art von table2.IDFromTable1und table1.ID?
Romain

5
Überprüfen Sie außerdem, ob die Zeichensätze für beide Tabellen identisch sind.
Carsten

Beide Tabellen-Engines sind innoDB. Ich bin mir nicht sicher, wo ich Zeichensätze finden soll, und beide sind vom Typ char. Die ID ist der Primärschlüssel in Tabelle1
Benutzer516883

2
Bitte geben Sie Tabellendefinitionen für Tabelle1 und Tabelle2 an. Wie haben Sie diesen Fehler bekommen? Verwenden Sie ein Tool zum Erstellen des Fremdschlüssels? Es scheint, dass es sich nicht um einen nativen MySQL-Fehler handelt.
Devart

@ user516883 - Benötigen Sie Hilfe, um Tabellendefinitionen zu erhalten? In HeidiSQL können Sie einfach auf die Registerkarte CREATE Code klicken .
Álvaro González

Antworten:


422

Ich bin mit HeidiSQL auf dasselbe Problem gestoßen. Der Fehler, den Sie erhalten, ist sehr kryptisch. Mein Problem war schließlich, dass die Fremdschlüsselspalte und die Referenzierungsspalte nicht vom gleichen Typ oder der gleichen Länge waren.

Die Fremdschlüsselspalte war SMALLINT(5) UNSIGNEDund die referenzierte Spalte war INT(10) UNSIGNED. Nachdem ich beide genau den gleichen Typ erstellt hatte, funktionierte die Erstellung des Fremdschlüssels perfekt.


58
Oder kann sein, dass die referenzierte Spalte kein Primärschlüssel ist
nawfal

9
Ein ähnliches Problem für mich - die Tabelle, auf die verwiesen wird, existiert noch nicht. Hoppla.
Amalgovinus

5
Ich habe total erlebt, was Jake getan hat, aber ich bin auf ein anderes FK-Problem (anderer Typ) unter HeidiSQL gestoßen. FK auf Varchars muss dieselbe Kollation sein. Hoffe das hilft jemand anderem in der Zukunft!
cbloss793

10
In meinem Fall lag es an der unterschiedlichen Codierung und Sortierung.
Khatri

1
@nawfal - Ich glaube, es muss nicht unbedingt ein Primärschlüssel sein, aber es muss einen Index haben. Primärschlüssel werden automatisch indiziert.
Itai

48

Ich hatte das gleiche Problem, als die übergeordnete Tabelle mit der MyISAMEngine erstellt wurde. Es ist ein dummer Fehler, den ich behoben habe:

ALTER TABLE parent_table ENGINE=InnoDB;

Vielen Dank, ich war verrückt danach. Irgendeine Idee, warum die Datenbank plötzlich die Engine für Tabellen wechseln würde?
Robert Franklin

28

Stellen Sie sicher, dass die Spalten identisch sind (vom gleichen Typ), und wenn dies nicht der Fall ist primary_key, stellen Sie sicher, dass dies der Fall ist INDEXED.


Es ist mir sogar passiert, dass es keinen Fehler gab, aber kein Fremdschlüssel hinzugefügt wurde (1 war und 1 war nicht wirklich), aber nach dem Hinzufügen von einfach KEY referencing_column(referencing_column) VOR der Definition beider Fremdschlüssel wurden beide erfolgreich hinzugefügt :)
jave.web

2
Nicht indizierte Schlüssel waren mein Problem.
Neil Masters

1
Ich hatte dieses Problem und das Problem war, dass ich einen zweispaltigen Primärschlüssel hatte und Sie die zweite Spalte des Primärschlüssels nicht als Fremdschlüssel verwenden können. Also habe ich gerade einen eigenen Index für die 2. Spalte des Primärschlüssels hinzugefügt und dann hat es funktioniert.
Firze

21

Die Syntax zum Definieren von Fremdschlüsseln ist sehr nachsichtig, aber für alle anderen, die sich damit auseinandersetzen, gilt die Tatsache, dass Fremdschlüssel "vom gleichen Typ" sein müssen, auch für die Sortierung, nicht nur für Datentyp, Länge und Bitsignatur.

Nicht, dass Sie die Kollatierung in Ihrem Modell mischen würden (oder?), Aber wenn Sie dies tun, stellen Sie sicher, dass Ihre Primär- und Fremdschlüsselfelder in phpmyadmin oder Heidi SQL oder was auch immer Sie verwenden, vom gleichen Kollatierungstyp sind.

Ich hoffe, das erspart Ihnen die vier Stunden Versuch und Irrtum, die es mich gekostet hat.


1
Vielen Dank! Es stellte sich heraus, dass mein Online-Host die ISAM-Engine verwendet und ich für lokale Entwickler InnoDB verwende. Als ich einen Tisch vom Host zum lokalen ... Boom gesichert habe.
Ben

Neuere Versionen von MariaDB scheinen utf8_mb4 als Standardzeichensatz zu verwenden (wenn dies nicht explizit in der Serverkonfiguration festgelegt wurde), ebenso COLLATE utf8mb4_unicode_cimein (unerwartetes) Problem (auf dem Entwicklungscomputer).
JonnyJD

13

Ich hatte das gleiche Problem, löste es aber.

So stellen Sie sicher , dass Spalte ‚ID‘ in ‚Tabelle1‘ hat UNIQUE Index!

Und natürlich müssen Typ und Länge der Spalten 'ID' und 'IDFromTable1' in diesen beiden Tabellen gleich sein. Aber das wissen Sie schon.


Du hast meinen Tag gerettet.
Kevenlolo

1
Froh, dass ich Helfen kann! ;)
Renat Gatin

Unsicher über die Details, aber ich hatte einen zusammengesetzten Schlüssel mit diesem Fehler, der durch Hinzufügen einzelner eindeutiger Indizes für die Spalten behoben wurde.
Halvor Holsten Strand

Die referenzierte Spalte muss indiziert sein, sie muss nicht eindeutig sein (obwohl dies der übliche Fall ist).
Barmar

10

Nur zur Fertigstellung.

Dieser Fehler kann auch auftreten, wenn Sie einen Fremdschlüssel mit VARCHAR (..) haben und sich der Zeichensatz der referenzierten Tabelle von der Tabelle unterscheidet, auf die verwiesen wird.

Beispiel: VARCHAR (50) in einer Latin1-Tabelle unterscheidet sich von VARCHAR (50) in einer UTF8-Tabelle.


1
Sogar utf8_unicode_ci und utf8_general_ci verursachen den Fehler
leuchtdiode

10

MySQL-Fehlertexte helfen nicht so viel. In meinem Fall hatte die Spalte die Einschränkung "nicht null", sodass die Einstellung "beim Löschen auf null gesetzt" nicht zulässig war


7

Wenn alles in Ordnung ist, fügen Sie es einfach ->unsigned();am Ende von hinzuforegin key .

Wenn dies nicht funktioniert, überprüfen Sie den Datentyp beider Felder. Sie müssen gleich sein.


5

Ich hatte das gleiche Problem, beide Spalten waren INT (11) NOT NULL, aber ich kann den Fremdschlüssel nicht erstellen. Ich musste Fremdschlüsselprüfungen deaktivieren, um es erfolgreich auszuführen:

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

Hoffe das hilft jemandem.


4
Eigentlich ist es FOREIGN_KEY_CHECKS
Xmanoux

Dies hat mir geholfen, weiter zu bestehen, aber mein Problem war, dass der Hauptindex in der Spalte
Bumerang

4

Eine weitere wahrscheinliche Ursache für die Anzeige dieses Fehlers. Die Reihenfolge, in der ich Tabellen erstellt habe, war falsch. Ich habe versucht, auf einen Schlüssel aus einer Tabelle zu verweisen, die noch nicht erstellt wurde.


4

(Last Resent) Auch wenn der Feldname und der Datentyp identisch sind, die Sortierung jedoch nicht identisch ist, führt dies ebenfalls zu diesem Problem.

Beispielsweise

    TBL NAME | DATENTYP | KOLLATION        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         utf8_general_ci

Versuchen Sie es zu ändern

    TBL NAME | DATENTYP | KOLLATION        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         latin1_general_ci

....

Das hat bei mir funktioniert.


3

Überprüfen Sie die Tabellen-Engine, beide Tabellen müssen dieselbe Engine sein, das hat mir sehr geholfen.


Guter Punkt! Ich habe es mit einer Zen Cart-Datenbank in MySQL zu tun, deren Tabellen standardmäßig alle in der MyISAM-Engine enthalten sind. Ich habe eine Tabelle mit der InnoDB-Engine hinzugefügt und versucht, dem Kern-Zen-Cart eine Fremdschlüsseleinschränkung aus meiner Tabelle hinzuzufügen. Es ist mit diesem obskuren "falsch geformten" Fehler fehlgeschlagen. Sie können den Motor für jeden Tisch mitSHOW TABLE STATUS LIKE 'table_name';
Neek

2

Ich hatte die gleichen Probleme.

Das Problem ist, dass die Referenzspalte kein Primärschlüssel ist.

Machen Sie es zu einem Primärschlüssel und das Problem ist gelöst.


Es muss keine PK sein, es kann auch EINZIGARTIG NICHT NULL sein.
Philipxy

Eigentlich ... in meinem Fall hat es einfach funktioniert, es einfach auf einen normalen Indextyp zu setzen.
Hendr1x

2

Obwohl die anderen Antworten sehr hilfreich sind, wollte ich nur meine Erfahrungen teilen.

Ich hatte das Problem, als ich eine Tabelle gelöscht hatte id, auf die in anderen Tabellen ( mit Daten ) bereits als Fremdschlüssel verwiesen wurde, und versuchte, die Tabelle mit einigen zusätzlichen Spalten neu zu erstellen / zu importieren.

Die Abfrage für die Neuerstellung (generiert in phpMyAdmin) sah folgendermaßen aus:

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`);

Wie Sie vielleicht bemerken, wurde der PRIMARY KEYIndex nach der Erstellung ( und dem Einfügen von Daten) festgelegt ) festgelegt, die das Problem verursacht hat.

Lösung

Die Lösung bestand darin, den PRIMARY KEYIndex für die Tabellendefinitionsabfrage für den idSchlüssel hinzuzufügen, auf den als Fremdschlüssel verwiesen wurde, und ihn gleichzeitig aus dem ALTER TABLETeil zu entfernen, in dem die Indizes festgelegt wurden:

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;

Es hat bei mir funktioniert. Ich hatte Angst, dass ich meine Software neu installieren muss;)
Dewlance

2

Dafür habe ich stundenlang verloren!

PK in einem Tisch war utf8in einem anderen war utf8_unicode_ci!


1

Versuchen Sie Folgendes auszuführen:

show create table Parent

// und überprüfe, ob der Typ für beide Tabellen gleich ist, wie myISAM oder innoDB usw.
// Andere Aspekte, die mit dieser Fehlermeldung überprüft werden müssen: Die als fremd verwendeten Spalten 
Schlüssel müssen indiziert sein, sie müssen vom gleichen Typ sein 
(wenn dh einer vom Typ smallint (5) und der andere vom Typ smallint (6) ist, 
es wird nicht funktionieren), und wenn sie ganze Zahlen sind, sollten sie ohne Vorzeichen sein.

// oder nach Zeichensätzen suchen
zeige Variablen wie "character_set_database";
zeige Variablen wie "collation_database";

// bearbeitet: versuche so etwas
ALTER TABLE table2
ADD CONSTRAINT fk_IdTable2
AUSLÄNDISCHER SCHLÜSSEL (Table1_Id)
REFERENZEN Tabelle1 (Tabelle1_Id)
ON UPDATE CASCADE 
ON DELETE CASCADE;

9
Versuchen Sie, SHOW ENGINE INNODB STATUS auszuführen, um weitere Details zu dem Fehler zu erhalten
Sudhir Bastakoti

@ SudhirBastakoti - +1! Das hat es für mich getan. Die Details sind hilfreich. Konnte das Problem schnell beheben.
Paul Carlton

1

Ich hatte das gleiche Problem mit Symfony 2.8.

Ich habe es zuerst nicht verstanden, weil es keine ähnlichen Probleme mit der Länge von Fremdschlüsseln usw. gab.

Schließlich musste ich im Projektordner Folgendes tun. (Ein Neustart des Servers hat nicht geholfen!)

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


1

danke S Doerin:

"Nur zur Vervollständigung. Dieser Fehler kann auch der Fall sein, wenn Sie einen Fremdschlüssel mit VARCHAR (..) haben und der Zeichensatz der referenzierten Tabelle sich von der Tabelle unterscheidet, auf die verwiesen wird. Beispiel: VARCHAR (50) in einer Latin1-Tabelle ist anders als das VARCHAR (50) in einer UTF8-Tabelle. "

Ich habe dieses Problem gelöst und die Art der Zeichen der Tabelle geändert. Die Erstellung hat latin1 und das richtige ist utf8.

Fügen Sie die nächste Zeile hinzu. DEFAULT CHARACTER SET = utf8;


1

Ich hatte Probleme bei der Verwendung der Tabelle "Ändern", um einen Fremdschlüssel zwischen zwei Tabellen hinzuzufügen, und half mir dabei, sicherzustellen, dass jede Spalte, zu der ich eine Fremdschlüsselbeziehung hinzufügen wollte, indiziert war. So tun Sie dies in PHP myAdmin: Gehen Sie zur Tabelle und klicken Sie auf die Registerkarte Struktur. Klicken Sie auf die Indexoption, um die gewünschte Spalte zu indizieren, wie im Screenshot gezeigt:

Geben Sie hier die Bildbeschreibung ein

Nachdem ich beide Spalten indiziert hatte, auf die ich mit meinen Fremdschlüsseln verweisen wollte, konnte ich die Änderungstabelle erfolgreich verwenden und die Fremdschlüsselbeziehung erstellen. Sie werden sehen, dass die Spalten wie im folgenden Screenshot indiziert sind:

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, wie die Postleitzahl in beiden Tabellen angezeigt wird.


1

Sie müssen überprüfen, ob beide in allen Eigenschaften gleich sind, einschließlich in "Sortierung".


1

Ich habe HeidiSQL verwendet und um dieses Problem zu lösen, musste ich einen Index in der referenzierten Tabelle erstellen, in dem alle Spalten referenziert sind.

Hinzufügen eines Index zur Tabelle Heidisql


Dasselbe gilt für mich in MySQL: InnoDB benötigt Indizes für Fremdschlüssel und referenzierte Schlüssel, damit Fremdschlüsselprüfungen schnell durchgeführt werden können und kein Tabellenscan erforderlich ist.
Hendr1x

1

Ich bin gerade auf das gleiche Problem gestoßen. In meinem Fall musste ich lediglich sicherstellen, dass die Tabelle, auf die ich im Fremdschlüssel verweise, vor der aktuellen Tabelle (früher im Code) erstellt werden muss. Wenn Sie also auf eine Variable (x * 5) verweisen, sollte das System wissen, was x ist (x muss in früheren Codezeilen deklariert werden). Dies hat mein Problem gelöst, hoffe, es wird jemand anderem helfen.


Ich hatte das gleiche Problem in MariaDB v10.3.18. Wir haben MySQL bereits verwendet und es warnte, dass ein Fremdschlüssel auf eine nicht vorhandene Tabelle verweist.
MarthyM

0

Ich hatte das gleiche Problem mit Laravel 5.1 Migration Schema Builder mit MariaDB 10.1.

Das Problem war, dass ich getippt hatte unigned beim Einstellen der Spalte anstelle von unsigned(der sBuchstabe fehlte) .

Nach dem Beheben wurde der Tippfehler für mich behoben.


0

Sogar ich bin auf das gleiche Problem mit MySQL und Liquibase gestoßen. Das Problem ist also: Die Tabelle, aus der Sie auf eine Spalte einer anderen Tabelle verweisen möchten, unterscheidet sich entweder im Fall eines Datentyps oder in Bezug auf die Größe des Datentyps.

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

Überprüfen Sie, ob Sie den Namen der Tabelle im richtigen Fall angegeben haben (wenn bei Tabellennamen in Ihrer Datenbank zwischen Groß- und Kleinschreibung unterschieden wird). In meinem Fall musste ich mich ändern

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

zu

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

Beachten Sie die customergeänderten zu CUSTOMER.


0

Oder Sie können DBDesigner4 verwenden, das über eine grafische Oberfläche verfügt, um Ihre Datenbank zu erstellen und mit FK zu verknüpfen. Klicken Sie mit der rechten Maustaste auf Ihre Tabelle und wählen Sie "Tabelle SQL erstellen erstellen", um den Code zu erstellen.

Geben Sie hier die Bildbeschreibung ein


0

Es ist ein altes Thema, aber ich habe etwas entdeckt. Beim Erstellen einer MySQL-Workbench werden auch die Beziehungen der anderen Tabelle abgerufen. Lassen Sie einfach die Säulen, auf die Sie sich beziehen. Löschen Sie andere automatisch hinzugefügte Spalten. Das funktioniert bei mir.


0

Mein Fall war, dass ich einen Tippfehler in der angegebenen Spalte hatte:

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")

Die Fehlermeldung ist ziemlich kryptisch und ich habe alles versucht - die Typen der Spalten, Kollatierungen, Engines usw. zu überprüfen.

Ich habe eine Weile gebraucht, um den Tippfehler zu notieren, und nachdem ich alles behoben hatte, funktionierte alles einwandfrei:

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

Ich bin mit diesem Problem konfrontiert. Der Fehler trat auf, wenn Sie den Primärschlüssel in einen anderen Datentyp wie:

Tabelle 1:

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

Tabelle 2:

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

Der Datentyp für die ID der zweiten Tabelle muss inkrementell sein


0

Das Problem ist sehr einfach zu lösen

Beispiel: Sie haben zwei Tabellen mit Namen für Benutzer und Beiträge und möchten einen Fremdschlüssel in der Beitragstabelle erstellen und verwenden phpMyAdmin

1) Fügen Sie in der Post- Tabelle eine neue Spalte hinzu ( Name : use_id | Typ : wie die ID in der Benutzertabelle | Länge : wie die ID in der Benutzertabelle | Standard : NULL | Attribute : ohne Vorzeichen | Index: INDEX)

2) Gehen Sie auf der Registerkarte Struktur zur Beziehungsansicht ( Einschränkungsname : automatisch festgelegt durch phpmyAdmin | Spaltenname : Wählen Sie Benutzer- ID | Tabelle : Benutzer | Schlüssel : ID, ...).

Es wurde einfach gelöst

javad mosavi iran / urmia

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.