Ich versuche, eine Tabelle in MySQL mit zwei Fremdschlüsseln zu erstellen, die auf die Primärschlüssel in zwei anderen Tabellen verweisen, erhalte jedoch den Fehler errno: 150, und die Tabelle wird nicht erstellt.
Hier ist die SQL für alle 3 Tabellen:
CREATE TABLE role_groups (
`role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
`name` varchar(20),
`description` varchar(200),
PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `roles` (
`role_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50),
`description` varchar(200),
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;
create table role_map (
`role_map_id` int not null `auto_increment`,
`role_id` int not null,
`role_group_id` int not null,
primary key(`role_map_id`),
foreign key(`role_id`) references roles(`role_id`),
foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;
Jede Hilfe wäre sehr dankbar.
mysql
foreign-keys
mysql-error-150
Bill Karwin
quelle
quelle
auto_increment
? Das ist nicht gültig. Auto_increment ist ein Schlüsselwort, kein Bezeichner.Antworten:
Ich hatte das gleiche Problem mit
ALTER TABLE ADD FOREIGN KEY
.Nach einer Stunde stellte ich fest, dass diese Bedingungen erfüllt sein müssen, um den Fehler 150 nicht zu erhalten:
Die übergeordnete Tabelle muss vorhanden sein, bevor Sie einen Fremdschlüssel definieren, um darauf zu verweisen. Sie müssen die Tabellen in der richtigen Reihenfolge definieren: Zuerst die übergeordnete Tabelle, dann die untergeordnete Tabelle. Wenn beide Tabellen aufeinander verweisen, müssen Sie eine Tabelle ohne FK-Einschränkungen erstellen, dann die zweite Tabelle erstellen und dann die FK-Einschränkung zur ersten Tabelle mit hinzufügen
ALTER TABLE
.Die beiden Tabellen müssen beide Fremdschlüsseleinschränkungen unterstützen, d
ENGINE=InnoDB
. H. Andere Speicher-Engines ignorieren Fremdschlüsseldefinitionen stillschweigend, sodass sie keinen Fehler oder keine Warnung zurückgeben, aber die FK-Einschränkung wird nicht gespeichert.Die Spalten, auf die in der übergeordneten Tabelle verwiesen wird, müssen die Spalten ganz links eines Schlüssels sein. Am besten, wenn der Schlüssel im Elternteil
PRIMARY KEY
oder istUNIQUE KEY
.Die FK-Definition muss auf die PK-Spalte (n) in derselben Reihenfolge wie die PK-Definition verweisen. Wenn beispielsweise die FK,
REFERENCES Parent(a,b,c)
darf die PK des Elternteils nicht in der angegebenen Reihenfolge für Spalten definiert werden(a,c,b)
.Die PK-Spalte (n) in der übergeordneten Tabelle müssen denselben Datentyp haben wie die FK-Spalte (n) in der untergeordneten Tabelle. Wenn sich beispielsweise eine PK-Spalte in der übergeordneten Tabelle befindet
UNSIGNED
, müssen SieUNSIGNED
die entsprechende Spalte im Feld Untergeordnete Tabelle definieren.Ausnahme: Die Länge der Zeichenfolgen kann unterschiedlich sein.
VARCHAR(10)
Kann zum Beispiel referenzierenVARCHAR(20)
oder umgekehrt.Alle FK-Spalten vom Typ "Zeichenfolge" müssen denselben Zeichensatz und dieselbe Sortierung wie die entsprechenden PK-Spalten haben.
Wenn die untergeordnete Tabelle bereits Daten enthält, muss jeder Wert in den FK-Spalten mit einem Wert in den PK-Spalten der übergeordneten Tabelle übereinstimmen. Überprüfen Sie dies mit einer Abfrage wie:
Dies muss null (0) nicht übereinstimmende Werte zurückgeben. Offensichtlich ist diese Abfrage ein allgemeines Beispiel. Sie müssen Ihre Tabellennamen und Spaltennamen ersetzen.
Weder die übergeordnete Tabelle noch die untergeordnete Tabelle können eine
TEMPORARY
Tabelle sein.Weder die übergeordnete Tabelle noch die untergeordnete Tabelle können eine
PARTITIONED
Tabelle sein.Wenn Sie eine FK mit der
ON DELETE SET NULL
Option deklarieren , müssen die FK-Spalten nullwertfähig sein.Wenn Sie einen Einschränkungsnamen für einen Fremdschlüssel deklarieren, muss der Einschränkungsname im gesamten Schema eindeutig sein, nicht nur in der Tabelle, in der die Einschränkung definiert ist. Zwei Tabellen haben möglicherweise keine eigene Einschränkung mit demselben Namen.
Wenn andere FKs in anderen Tabellen auf dasselbe Feld verweisen, für das Sie die neue FK erstellen möchten, und diese fehlerhaft sind (dh eine andere Sortierung aufweisen), müssen sie zuerst konsistent gemacht werden. Dies kann auf frühere Änderungen zurückzuführen sein, bei denen
SET FOREIGN_KEY_CHECKS = 0;
eine versehentlich definierte inkonsistente Beziehung verwendet wurde. In der Antwort von @ andrewdotn unten finden Sie Anweisungen zum Identifizieren dieser Problem-FKs.Hoffe das hilft.
quelle
int(11) unsigned NOT NULL
vsint(11) NOT NULL
.ON DELETE
Regel Ihres CONSTRAINT lautet,SET NULL
stellen Sie sicher, dass der Fremdschlüssel tatsächlich NULL sein kann! Ich verbrachte 30 Minuten damit, diese Antwort immer wieder zu lesen, um sicherzustellen, dass meine Tabellen die Bedingungen erfüllten, aber immer noch Fehler 150 erhielten. Dann bemerkte ich, dass mein FK ein NICHT NULL-Feld war, was bedeutete, dass die Regel nicht angewendet werden konnte.Die generische Meldung "errno 150" von MySQL bedeutet, dass eine Fremdschlüsseleinschränkung nicht korrekt gebildet wurde . Wie Sie wahrscheinlich bereits wissen, wenn Sie diese Seite lesen, ist die generische Fehlermeldung "errno: 150" nicht hilfreich. Jedoch:
Sie können die eigentliche Fehlermeldung erhalten, indem Sie ausführen
SHOW ENGINE INNODB STATUS;
und dannLATEST FOREIGN KEY ERROR
in der Ausgabe suchen .Beispiel für diesen Versuch, eine Fremdschlüsseleinschränkung zu erstellen:
schlägt mit dem Fehler fehl
Can't create table 'test.t2' (errno: 150)
. Das sagt niemandem etwas Nützliches, außer dass es ein Fremdschlüsselproblem ist. Aber rennSHOW ENGINE INNODB STATUS;
und es wird sagen:Das Problem besteht darin, dass kein Index gefunden werden kann.
SHOW INDEX FROM t1
zeigt, dass es für die Tabelle überhaupt keine Indizes gibtt1
. Korrigieren Sie dies, indem Sie beispielsweise einen Primärschlüssel definierent1
, und die Fremdschlüsseleinschränkung wird erfolgreich erstellt.quelle
SHOW ENGINE INNODB STATUS
half mir sofort, ein Problem zu identifizieren, das ich seit fast einer Stunde zu diagnostizieren versuchte. Vielen Dank.SET FOREIGN_KEY_CHECKS = 0;
während eines Imports / einer Änderung verwendet, die fehlerhaft war irgendeinmal. Große Hilfe, danke.Stellen Sie sicher, dass die Eigenschaften der beiden Felder, die Sie mit einer Einschränkung verknüpfen möchten, genau gleich sind.
Häufig werden Sie von der Eigenschaft "ohne Vorzeichen" in einer ID-Spalte aufgefangen.
quelle
Wie ist der aktuelle Status Ihrer Datenbank, wenn Sie dieses Skript ausführen? Ist es komplett leer? Ihr SQL läuft für mich einwandfrei, wenn Sie eine Datenbank von Grund auf neu erstellen, aber errno 150 hat normalerweise mit dem Löschen und Neuerstellen von Tabellen zu tun, die Teil eines Fremdschlüssels sind. Ich habe das Gefühl, dass Sie nicht mit einer 100% frischen und neuen Datenbank arbeiten.
Wenn Sie beim "Quellieren" Ihrer SQL-Datei einen Fehler machen, sollten Sie in der Lage sein, den Befehl "SHOW ENGINE INNODB STATUS" unmittelbar nach dem Befehl "source" an der MySQL-Eingabeaufforderung auszuführen, um detailliertere Fehlerinformationen anzuzeigen.
Vielleicht möchten Sie auch den manuellen Eintrag lesen:
quelle
Für Personen, die diesen Thread mit demselben Problem anzeigen:
Es gibt viele Gründe für solche Fehler. Eine ziemlich vollständige Liste der Ursachen und Lösungen von Fremdschlüsselfehlern in MySQL (einschließlich der hier beschriebenen) finden Sie unter folgendem Link:
MySQL-Fremdschlüsselfehler und Errno 150
quelle
Für andere, die diesen SO-Eintrag über Google finden: Stellen Sie sicher, dass Sie nicht versuchen, eine SET NULL-Aktion für eine Fremdschlüsselspalte auszuführen, die als "NOT NULL" definiert ist. Das verursachte große Frustration, bis ich mich daran erinnerte, einen CHECK ENGINE INNODB STATUS durchzuführen.
quelle
Auf jeden Fall ist das nicht der Fall, aber ich fand diesen Fehler ziemlich häufig und nicht offensichtlich. Das Ziel eines
FOREIGN KEY
könnte nicht seinPRIMARY KEY
. Die Antwort, die für mich nützlich wird, lautet:Ein FOREIGN KEY muss immer auf ein PRIMARY KEY true-Feld einer anderen Tabelle zeigen.
quelle
Wie von @andrewdotn gezeigt, ist es am besten, den detaillierten Fehler (
SHOW ENGINE INNODB STATUS;
) anstelle nur eines Fehlercodes anzuzeigen .Einer der Gründe könnte sein, dass ein Index mit demselben Namen bereits vorhanden ist und sich möglicherweise in einer anderen Tabelle befindet. In der Praxis empfehle ich, den Tabellennamen vor dem Indexnamen zu setzen, um solche Kollisionen zu vermeiden. zB statt zu
idx_userId
benutzenidx_userActionMapping_userId
.quelle
Bitte stellen Sie zunächst sicher, dass
Ich hatte das gleiche Problem und habe es behoben. Ich hatte INT für ein Feld ohne Vorzeichen und für ein anderes Feld nur eine Ganzzahl.
quelle
Hilfreicher Tipp, verwenden Sie ihn
SHOW WARNINGS;
nach dem Versuch IhrerCREATE
Abfrage und Sie erhalten den Fehler sowie die detailliertere Warnung:In diesem Fall ist es also Zeit, meine Tabelle neu zu erstellen!
quelle
Dies geschieht normalerweise, wenn Sie versuchen, eine Quelldatei in eine vorhandene Datenbank zu übertragen. Löschen Sie zuerst alle Tabellen (oder die Datenbank selbst). Und dann Quelldatei mit
SET foreign_key_checks = 0;
am Anfang undSET foreign_key_checks = 1;
am Ende.quelle
Ich habe einen anderen Grund gefunden, warum dies fehlschlägt ... Groß- und Kleinschreibung von Tabellennamen.
Für diese Tabellendefinition
Diese Tabellendefinition funktioniert
während dieser scheitert
Die Tatsache, dass es unter Windows funktionierte und unter Unix fehlschlug, dauerte ein paar Stunden, um es herauszufinden. Hoffe das hilft jemand anderem.
quelle
MySQL Workbench 6.3 für Mac OS.
Problem: Fehler Nr. 150 in Tabelle X beim Versuch, Forward Engineering in einem DB-Diagramm durchzuführen. 20 von 21 waren erfolgreich, 1 ist fehlgeschlagen. Wenn FKs in Tabelle X gelöscht wurden, wurde der Fehler in eine andere Tabelle verschoben, die zuvor nicht fehlgeschlagen war.
Alle Tabellen-Engine wurde auf myISAM geändert und es hat einwandfrei funktioniert.
quelle
Es lohnt sich auch zu überprüfen, ob Sie nicht versehentlich mit der falschen Datenbank arbeiten. Dieser Fehler tritt auf, wenn die Fremdtabelle nicht vorhanden ist. Warum muss MySQL so kryptisch sein?
quelle
Stellen Sie sicher, dass die Fremdschlüssel im übergeordneten Element nicht als eindeutig aufgeführt sind. Ich hatte das gleiche Problem und löste es, indem ich es als nicht eindeutig abgrenzte.
quelle
In meinem Fall lag es an der Tatsache, dass das Feld, das ein Fremdschlüsselfeld war, einen zu langen Namen hatte, d. H.
foreign key (some_other_table_with_long_name_id)
. Versuchen Sie etwas kürzer. Die Fehlermeldung ist in diesem Fall etwas irreführend.Wie bereits bei @Jon erwähnt, müssen die Felddefinitionen identisch sein (achten Sie auf den
unsigned
Subtyp).quelle
(Randnotizen zu groß für einen Kommentar)
AUTO_INCREMENT
In einer Zuordnungstabelle ist keine ID erforderlich . werde es los.Ändern Sie das
PRIMARY KEY
in(role_id, role_group_id)
(in beliebiger Reihenfolge). Dies beschleunigt den Zugriff.Da Sie wahrscheinlich beide Richtungen zuordnen möchten, fügen Sie auch eine
INDEX
mit diesen beiden Spalten in umgekehrter Reihenfolge hinzu. (Es ist nicht nötig, es zu machenUNIQUE
.)Weitere Tipps: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
quelle
Wenn die Fremdschlüsseleinschränkung auf dem
varchar
Typ basiert , muss zusätzlich zu der vonmarv-el
der Zielspalte bereitgestellten Liste eine eindeutige Einschränkung vorhanden sein.quelle
Führen Sie die folgende Zeile aus, bevor Sie eine Tabelle erstellen: SET FOREIGN_KEY_CHECKS = 0;
Die Option FOREIGN_KEY_CHECKS gibt an, ob Fremdschlüsseleinschränkungen für InnoDB-Tabellen überprüft werden sollen.
- Geben Sie an, dass Fremdschlüsseleinschränkungen überprüft werden sollen (dies ist die Standardeinstellung).
- Überprüfen Sie keine Fremdschlüsseleinschränkungen
SET FOREIGN_KEY_CHECKS = 0;
Verwendungszweck: Das vorübergehende Deaktivieren von referenziellen Einschränkungen (FOREIGN_KEY_CHECKS auf 0 setzen) ist nützlich, wenn Sie die Tabellen neu erstellen und Daten in einer beliebigen Eltern-Kind-Reihenfolge laden müssen
quelle
Ich habe das gleiche Problem festgestellt, aber ich überprüfe, ob ich die übergeordnete Tabelle nicht hatte. Also bearbeite ich einfach die übergeordnete Migration vor der untergeordneten Migration. Mach es einfach.
quelle