Fügen Sie der vorhandenen Tabelle einen Fremdschlüssel hinzu


324

Ich möchte einer Tabelle namens "katalog" einen Fremdschlüssel hinzufügen.

ALTER TABLE katalog 
ADD CONSTRAINT `fk_katalog_sprache` 
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

Wenn ich dies versuche, wird folgende Fehlermeldung angezeigt:

Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150)

Fehler im INNODB-Status:

120405 14:02:57 Fehler in der Fremdschlüsseleinschränkung der Tabelle mytable. # Sql-7fb1_7d3a:

FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL:
Cannot resolve table name close to:
(`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL

Wenn ich diese Abfrage verwende, funktioniert sie, aber mit der falschen Aktion "Beim Löschen":

ALTER TABLE `katalog` 
ADD FOREIGN KEY (`Sprache` ) REFERENCES `sprache` (`ID` )

Beide Tabellen sind InnoDB und beide Felder sind "INT (11) not null". Ich verwende MySQL 5.1.61. Der Versuch, diese ALTER-Abfrage mit MySQL Workbench (neueste Version) auf einem MacBook Pro auszulösen.

Tabellenanweisungen erstellen:

CREATE TABLE `katalog` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`AnzahlSeiten` int(4) unsigned NOT NULL,
`Sprache` int(11) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `katalogname_uq` (`Name`)
 ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC$$

CREATE TABLE `sprache` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
 `Bezeichnung` varchar(45) NOT NULL,
 PRIMARY KEY (`ID`),
 UNIQUE KEY `Bezeichnung_UNIQUE` (`Bezeichnung`),
KEY `ix_sprache_id` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

1
Da Sie die Ausgabe von nicht gepostet haben SHOW CREATE TABLE, kann ich nur fragen - ist der Spaltenname wirklich ID, in Großbuchstaben?
NB

Nun, es ist jetzt leichter zu erkennen - kataloghat int(11) unsigned. sprachehat das usignedTeil nicht, daher sind zwei Spalten nicht gleich.
NB

Meinen Sie, dass beide Primärfelder denselben Datentyp haben müssen?
frgtv10

2
Dies ist das Problem bei Ihrem Design: Erstens verweisen Sie auf zwei auto_incrementSpalten, was schlecht ist. Außerdem heißt es im MySQL-Handbuch : Corresponding columns in the foreign key and the referenced key must have similar internal data types inside InnoDB so that they can be compared without a type conversion. The size and sign of integer types must be the same. The length of string types need not be the same. For nonbinary (character) string columns, the character set and collation must be the same.. Daher ja, ähnlicher Datentyp und das gleiche Vorzeichen.
NB

2
Ich verweise nicht auf zwei auto_increment-Felder. katalog.Sprache (nicht auto) -> sprache.ID (auto)
frgtv10

Antworten:


559

Führen Sie die folgenden Schritte aus, um einer vorhandenen Tabelle (Benutzern) einen Fremdschlüssel (grade_id) hinzuzufügen:

ALTER TABLE users ADD grade_id SMALLINT UNSIGNED NOT NULL DEFAULT 0;
ALTER TABLE users ADD CONSTRAINT fk_grade_id FOREIGN KEY (grade_id) REFERENCES grades(id);

12
Gründe helfen mir zu verstehen und mich zu erinnern. Dies liegt daran, dass Sie einem nicht vorzeichenlosen Feld keinen Fremdschlüssel hinzufügen können, richtig?
PixMach

8
@PixMach, die Antwort ist nein. Sie können Ganzzahlen als Fremdschlüssel signiert haben. Wie NB in ​​der Frage vermerkt hat, müssen Typ und Vorzeichen der Felder übereinstimmen. Wenn Ihr Primärschlüssel in der Nachschlagetabelle UNSIGNED ist, muss das Fremdschlüsselfeld ebenfalls UNSIGNED sein. Wenn das Primärschlüsselfeld SIGNIERT ist, muss auch das Fremdschlüsselfeld signiert sein. Stellen Sie sich das so vor: Unabhängig davon, wie die Spalte in der einen Tabelle wie in einer SHOW CREATE TABLE definiert ist, muss sie in der anderen Tabelle dieselbe Definition haben.
Ben Keene

1
Beachten Sie, dass dies auch mit einer einzigen Abfrage erfolgen kann (möglicherweise besser bei einem Fehler usw.)
Stijn de Witt

6
Ich musste "SET FOREIGN_KEY_CHECKS = 0;" vor dem Ausführen des Befehls ADD CONSTRAINT oder SQL würde sich beschweren "Kann keine untergeordnete Zeile hinzufügen oder aktualisieren: Eine Fremdschlüsseleinschränkung schlägt fehl".
Erin Geyer

2
Führen Sie nicht einfach "SET FOREIGN_KEY_CHECKS = 0;" Wenn Sie die Fehlermeldung "Eine Fremdschlüsseleinschränkung schlägt fehl" erhalten, haben Sie offensichtlich schlechte Daten, die Sie beheben müssen, oder Sie werden später größere Probleme bekommen.
MazeChaZer

72

Verwenden Sie einfach diese Abfrage, ich habe sie gemäß meinem Szenario ausprobiert und sie funktioniert gut

ALTER TABLE katalog ADD FOREIGN KEY (`Sprache`) REFERENCES Sprache(`ID`);

25

Einfache Schritte ...

ALTER TABLE t_name1 ADD FOREIGN KEY (column_name) REFERENCES t_name2(column_name)

15

Überprüfen Sie diesen Link. Es hat mir bei Errno 150 geholfen: http://verysimple.com/2006/10/22/mysql-error-number-1005-cant-create-table-mydbsql-328_45frm-errno-150/

Auf meinem Kopf fallen mir zwei Dinge ein.

  • Ist Ihr Fremdschlüsselindex ein eindeutiger Name in der gesamten Datenbank (Nr. 3 in der Liste)?
  • Versuchen Sie, die Tabelle PK beim Update auf NULL zu setzen (# 5 in der Liste)?

Ich vermute, das Problem liegt bei der Einstellung NULL beim Update (wenn mein Gehirn heute nicht rückwärts läuft, wie es so oft der Fall ist ...).

Bearbeiten: Ich habe die Kommentare zu Ihrem ursprünglichen Beitrag verpasst. Int-Spalten ohne Vorzeichen / ohne Vorzeichen haben Ihren Fall möglicherweise gelöst. Hoffe mein Link hilft jemandem in der Zukunft zu denken.


13
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

Aber Ihr Tisch hat:

CREATE TABLE `katalog` (
`Sprache` int(11) NOT NULL,

Es kann nicht die Spalte Sprache auf NULL gesetzt , weil es als NOT NULL definiert ist.


5

MySQL führt diese Abfrage aus:

ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;

Prost!


5

Wie repariert man Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150) in mysql.

  1. Ändern Sie Ihre Tabelle und fügen Sie einen Index hinzu.

    ALTER TABLE users ADD INDEX index_name (index_column)
  2. Fügen Sie nun die Einschränkung hinzu

    ALTER TABLE foreign_key_table
    ADD CONSTRAINT foreign_key_name FOREIGN KEY (foreign_key_column)
    REFERENCES primary_key_table (primary_key_column) ON DELETE NO ACTION
    ON UPDATE CASCADE;

Beachten Sie, dass es nicht funktioniert, wenn Sie keinen Index hinzufügen.

Nachdem ich ungefähr 6 Stunden damit gekämpft hatte, kam ich auf die Lösung, von der ich hoffe, dass sie eine Seele rettet.


4

Denken Sie beim Hinzufügen einer Fremdschlüsseleinschränkung zu einer Tabelle mit ALTER TABLE daran, zuerst die erforderlichen Indizes zu erstellen.

  1. Index erstellen
  2. Tabelle ändern

Ich habe für beide einen Index erstellt. Wenn ich versuche auszuführen, erhalte ich die gleiche Fehlermeldung wie zuvor. Wenn ich den Teil "Beim Löschen beim Update"
ablehne,

@ frgtv10 am wahrscheinlichsten kollidieren die Tabellendaten mit "on delete".
Maksym Polshcha

3

Versuchen Sie alles in einer Abfrage

  ALTER TABLE users ADD grade_id SMALLINT UNSIGNED NOT NULL DEFAULT 0,
      ADD CONSTRAINT fk_grade_id FOREIGN KEY (grade_id) REFERENCES grades(id);

0

Dies geschieht im Wesentlichen, weil sich Ihre Tabellen in zwei verschiedenen Zeichensätzen befinden. Als Beispiel wird eine Tabelle in charset = utf-8 und andere Tabellen in CHARSET = latin1 erstellt, damit Sie diesen Tabellen einen Foriegn-Schlüssel hinzufügen können. Verwenden Sie in beiden Tabellen den gleichen Zeichensatz, um weitere Schlüssel hinzuzufügen. Fehler 1005 falsch gebildete Schlüsselbeschränkung kann daraus behoben werden


0

Ich bin durch das gleiche Problem gekommen. In meinem Fall hat die Tabelle bereits Daten und es gab Schlüssel in dieser Tabelle, die nicht in der Referenztabelle vorhanden waren. Also musste ich diese Zeilen löschen, die die Einschränkungen nicht respektierten und alles funktionierte.


0

Schritt 1: Führen Sie dieses Skript aus

SET FOREIGN_KEY_CHECKS=0;

Schritt 2: Spalte hinzufügen

ALTER TABLE mileage_unit ADD COLUMN COMPANY_ID BIGINT(20) NOT NULL

Schritt 3: Fügen Sie der hinzugefügten Spalte einen Fremdschlüssel hinzu

ALTER TABLE mileage_unit
ADD FOREIGN KEY (COMPANY_ID) REFERENCES company_mst(COMPANY_ID);

Schritt 4: Führen Sie dieses Skript aus

SET FOREIGN_KEY_CHECKS=1;

-1
 ALTER TABLE TABLENAME ADD FOREIGN KEY (Column Name) REFERENCES TableName(column name)

Beispiel:-

ALTER TABLE Department ADD FOREIGN KEY (EmployeeId) REFERENCES Employee(EmployeeId)

1
Bitte fügen Sie Ihrem Code einige Erklärungen hinzu, damit andere daraus lernen können
Nico Haase
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.