wake-up-neo.com

MySQL Erstellen von Tabellen mit Fremdschlüsseln mit der folgenden Fehlernummer: 150

Ich versuche, eine Tabelle in MySQL mit zwei Fremdschlüsseln zu erstellen, die auf die Primärschlüssel in zwei anderen Tabellen verweisen, aber ich erhalte die Fehlermeldung "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.

93
user176842

Ich hatte das gleiche Problem mit ALTER TABLE ADD FOREIGN KEY.

Nach einer Stunde habe ich festgestellt, dass diese Bedingungen erfüllt sein müssen, um Fehler 150 nicht zu erhalten:

  1. 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 sich beide Tabellen gegenseitig referenzieren, müssen Sie eine Tabelle ohne FK-Einschränkungen erstellen, dann die zweite Tabelle erstellen und die FK-Einschränkung mit ALTER TABLE zur ersten Tabelle hinzufügen. 

  2. Die beiden Tabellen müssen beide Fremdschlüsseleinschränkungen unterstützen, d. H. ENGINE=InnoDB. Andere Speicher-Engines ignorieren Fremdschlüsseldefinitionen unbemerkt und geben daher keine Fehler oder Warnungen zurück. Die FK-Einschränkung wird jedoch nicht gespeichert.

  3. Die referenzierten Spalten in der übergeordneten Tabelle müssen die ganz linken Spalten eines Schlüssels sein. Am besten, wenn der Schlüssel in Parent PRIMARY KEY oder UNIQUE KEY ist.

  4. Die FK-Definition muss auf die PK-Spalte (n) in derselben Reihenfolge verweisen wie die PK-Definition. Wenn zum Beispiel die FK REFERENCES Parent(a,b,c), dann darf der PK des übergeordneten Elements nicht in der Reihenfolge (a,c,b) für Spalten definiert werden.

  5. Die PK-Spalte (n) in der Parent-Tabelle müssen denselben Datentyp haben wie die FK-Spalte (n) in der Child-Tabelle. Wenn beispielsweise eine PK-Spalte in der übergeordneten Tabelle UNSIGNED ist, müssen Sie unbedingt UNSIGNED für die entsprechende Spalte im Feld Child-Tabelle definieren. 

    Ausnahme: Die Länge der Zeichenfolgen kann unterschiedlich sein. Zum Beispiel kann VARCHAR(10) auf VARCHAR(20) verweisen oder umgekehrt.

  6. Alle FK-Spalten des Stringtyps müssen denselben Zeichensatz und dieselbe Sortierung wie die entsprechenden PK-Spalten haben.

  7. Wenn sich bereits Daten in der untergeordneten Tabelle befinden, muss jeder Wert in der FK-Spalte (n) mit einem Wert in der PK-Spalte der übergeordneten Tabelle übereinstimmen. Überprüfen Sie dies mit einer Abfrage wie:

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

    Dies muss null (0) nicht übereinstimmende Werte zurückgeben. Diese Abfrage ist offensichtlich ein allgemeines Beispiel. Sie müssen Ihre Tabellennamen und Spaltennamen ersetzen.

  8. Weder die Parent-Tabelle noch die Child-Tabelle können eine TEMPORARY-Tabelle sein.

  9. Weder die Parent-Tabelle noch die Child-Tabelle können eine PARTITIONED-Tabelle sein.

  10. Wenn Sie eine FK mit der Option ON DELETE SET NULL deklarieren, müssen die FK-Spalten nullfähig sein.

  11. Wenn Sie einen Constraint-Namen für einen Fremdschlüssel deklarieren, muss der Constraint-Name im gesamten Schema eindeutig sein, nicht nur in der Tabelle, in der die Constraint definiert ist. Zwei Tabellen haben möglicherweise keine eigene Einschränkung mit demselben Namen.

Hoffe das hilft.

230
marv-el

Die generische "errno 150" -Meldung von MySQL bedeutet " bedeutet, dass eine Fremdschlüsseleinschränkung nicht richtig gebildet wurde ." Jedoch:

Sie können die tatsächliche Fehlermeldung erhalten, indem Sie SHOW ENGINE INNODB STATUS; ausführen und dann in der Ausgabe nach LATEST FOREIGN KEY ERROR suchen.

Beispielsweise versuchen Sie, eine Fremdschlüsseleinschränkung zu erstellen:

CREATE TABLE t1
(id INTEGER);

CREATE TABLE t2
(t1_id INTEGER,
 CONSTRAINT FOREIGN KEY (t1_id) REFERENCES t1 (id));

schlägt mit dem Fehler Can't create table 'test.t2' (errno: 150) fehl. Das sagt niemandem etwas Nützliches, außer dass es ein Fremdschlüsselproblem ist. Starten Sie SHOW ENGINE INNODB STATUS; und es wird sagen:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
130811 23:36:38 Error in foreign key constraint of table test/t2:
FOREIGN KEY (t1_id) REFERENCES t1 (id)):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

Das Problem ist, dass es keinen Index findet. SHOW INDEX FROM t1 zeigt an, dass es für die Tabelle t1 überhaupt keine Indizes gibt. Beheben Sie dies, indem Sie beispielsweise einen Primärschlüssel für t1 definieren, und die Fremdschlüsseleinschränkung wird erfolgreich erstellt.

60
andrewdotn

Stellen Sie sicher, dass die Eigenschaften der beiden Felder, die Sie mit einer Einschränkung verknüpfen möchten, identisch sind.

Häufig werden Sie durch die Eigenschaft "unsigned" in einer ID-Spalte aufgefangen.

ALTER TABLE `dbname`.`tablename` CHANGE `fieldname` `fieldname` int(10) UNSIGNED NULL;
25
Jon Winstanley

Wie ist der aktuelle Status Ihrer Datenbank, wenn Sie dieses Skript ausführen? Ist es völlig leer Wenn Sie eine Datenbank von Grund auf neu erstellen, läuft Ihre SQL-Version einwandfrei. Errno 150 hat jedoch 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% neuen und neuen Datenbank arbeiten.

Wenn Sie bei der "Quelle" Ihrer SQL-Datei einen Fehler machen, sollten Sie den Befehl "SHOW ENGINE INNODB STATUS" an der MySQL-Eingabeaufforderung sofort nach dem Befehl "source" ausführen können, um detailliertere Fehlerinformationen anzuzeigen.

Möglicherweise möchten Sie auch die manuelle Eingabe überprüfen:

Wenn Sie eine Tabelle neu erstellen, die gelöscht wurde, muss sie eine Definition haben, die den Fremdschlüsseleinschränkungen entspricht, auf die sie verweist. Es muss über die richtigen Spaltennamen und -typen verfügen, und es muss Indizes für die referenzierten Schlüssel enthalten, wie zuvor angegeben. Wenn diese nicht erfüllt sind, gibt MySQL die Fehlernummer 1005 zurück und verweist auf Fehler 150 in der Fehlermeldung. Wenn MySQL eine Fehlernummer 1005 aus einer CREATE TABLE-Anweisung meldet und die Fehlernachricht auf Fehler 150 verweist, schlug die Tabellenerstellung fehl, da eine Fremdschlüsseleinschränkung nicht ordnungsgemäß gebildet wurde.

- MySQL 5.1 Referenzhandbuch .

10

Für Personen, die diesen Thread mit demselben Problem anzeigen:

Es gibt viele Gründe, solche Fehler zu erhalten. Eine ziemlich vollständige Liste der Ursachen und Lösungen von Fremdschlüsselfehlern in MySQL (einschließlich der hier behandelten) finden Sie hier:

MySQL-Fremdschlüsselfehler und Errno 150

5
juacala

Für andere, die diesen Eintrag finden SO über Google: Stellen Sie sicher, dass Sie nicht versuchen, eine SET NULL-Aktion für eine als "NOT NULL" definierte Fremdschlüsselspalte auszuführen. Das löste großen Frust aus, bis ich daran dachte, einen CHECK ENGINE INNODB STATUS zu machen.

4
Eric Lawler

Wie @andrewdotn zeigt, ist es am besten, den detaillierten Fehler (SHOW ENGINE INNODB STATUS;) anstelle eines Fehlercodes anzuzeigen.

Ein Grund könnte sein, dass bereits ein Index mit demselben Namen existiert, möglicherweise in einer anderen Tabelle. Als Übung empfehle ich vor dem Indexnamen den Tabellennamen vorzustellen, um solche Kollisionen zu vermeiden. z.B. Verwenden Sie statt idx_userIdidx_userActionMapping_userId.

3
MuchMore

Auf jeden Fall ist es nicht der Fall, aber ich fand diesen Fehler häufig und nicht naheliegend. Das Ziel eines FOREIGN KEY könnte nicht PRIMARY KEY sein. Die Antwort, die für mich nützlich wird, lautet:

Ein FOREIGN KEY muss immer auf ein wahres PRIMARY KEY-Feld einer anderen Tabelle zeigen.

CREATE TABLE users(
   id INT AUTO_INCREMENT PRIMARY KEY,
   username VARCHAR(40));

CREATE TABLE userroles(
   id INT AUTO_INCREMENT PRIMARY KEY,
   user_id INT NOT NULL,
   FOREIGN KEY(user_id) REFERENCES users(id));
3
I159

Hilfreicher Tipp: Verwenden Sie SHOW WARNINGS;, nachdem Sie Ihre CREATE-Abfrage getestet haben. Sie erhalten den Fehler sowie die ausführlichere Warnung:

    ---------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                                                                 |
+---------+------+--------------------------------------------------------------------------                          --------------------------------------------------------------------------------------------                          ---------------+
| Warning |  150 | Create table 'fakeDatabase/exampleTable' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
|
| Error   | 1005 | Can't create table 'exampleTable' (errno:150)                                                                                                                                                                           |
+---------+------+--------------------------------------------------------------------------                          --------------------------------------------------------------------------------------------                          ---------------+

In diesem Fall also Zeit, meine Tabelle neu zu erstellen!

2
sturrockad

Bitte stellen Sie zuerst sicher, dass dies der Fall ist

  1. sie verwenden InnoDB-Tabellen.
  2. feld für FOREIGN KEY hat denselben Typ und dieselbe Länge (!) wie das Quellfeld.

Ich hatte das gleiche Problem und habe es behoben. Ich hatte INT für ein Feld vorzeichenlos und für das andere Feld nur Integer.

2
Juljan

Dies ist normalerweise der Fall, wenn Sie versuchen, die Datei in eine vorhandene Datenbank zu quellen. Löschen Sie zuerst alle Tabellen (oder die Datenbank selbst). Und dann Quelldatei mit SET foreign_key_checks = 0; am Anfang und SET foreign_key_checks = 1; am Ende.

1
wholenewstrain

Ich habe einen anderen Grund gefunden, warum dies fehlschlägt.

Für diese Tabellendefinition

CREATE TABLE user (
  userId int PRIMARY KEY AUTO_INCREMENT,
  username varchar(30) NOT NULL
) ENGINE=InnoDB;

Diese Tabellendefinition funktioniert

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES **u**ser(userId)
) ENGINE=InnoDB;

während dieser versagt

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES User(userId)
) ENGINE=InnoDB;

Die Tatsache, dass es unter Windows funktionierte und unter Unix fehlgeschlagen ist, hat einige Stunden gedauert. Hoffe das hilft jemand anderem.

1
Tim

MySQL Workbench 6.3 für Mac OS. 

Problem: Fehler 150 in Tabelle X beim Versuch, Forward Engineering für ein DB-Diagramm auszuführen. Wenn FKs in Tabelle X gelöscht wurden, wurde der Fehler in eine andere Tabelle verschoben, die zuvor nicht fehlgeschlagen war. 

Alle Tabellen-Engine zu myISAM geändert und es hat gut funktioniert. 

 enter image description here

1

Stellen Sie sicher, dass die Fremdschlüssel im übergeordneten Element nicht eindeutig sind. Ich hatte das gleiche Problem und löste es, indem ich es als nicht eindeutig abgrenzte.

0
Raza

Es lohnt sich auch zu überprüfen, dass Sie nicht versehentlich mit der falschen Datenbank arbeiten. Dieser Fehler tritt auf, wenn die Fremdtabelle nicht vorhanden ist. Warum muss MySQL so kryptisch sein?

0
SystemParadox

Wenn die Fremdschlüsseleinschränkung auf dem Typ varchar basiert, muss die target-Spalte zusätzlich zu der von marv-el bereitgestellten Liste eine eindeutige Einschränkung aufweisen.

0
Ralph

(Seitennotizen zu groß für einen Kommentar)

In einer Mapping-Tabelle ist keine AUTO_INCREMENT-ID erforderlich. werde es los.

Ändern Sie den PRIMARY KEY in (role_id, role_group_id) (in beliebiger Reihenfolge). Dadurch werden die Zugriffe schneller.

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 notwendig, es UNIQUE zu machen.)

Weitere Tipps: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta

0
Rick James

In meinem Fall lag es daran, 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 es etwas kürzer. Die Fehlermeldung ist in diesem Fall etwas irreführend.

Wie @Jon bereits erwähnt hat, müssen die Felddefinitionen identisch sein (achten Sie auf den Subtyp unsigned).

0
Kangur