Agregar clave externa a la tabla existente

324

Quiero agregar una clave externa a una tabla llamada "katalog".

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

Cuando trato de hacer esto, recibo este mensaje de error:

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

Error en el estado INNODB:

120405 14:02:57 Error en la restricción de clave externa de la tabla 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

Cuando uso esta consulta funciona, pero con una acción incorrecta "al eliminar":

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

Ambas tablas son InnoDB y ambos campos son "INT (11) no nulo". Estoy usando MySQL 5.1.61. Intentando activar esta consulta ALTER con MySQL Workbench (la más nueva) en un MacBook Pro.

Tabla Crear declaraciones:

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
frgtv10
fuente
1
Como no publicó la salida de SHOW CREATE TABLE, solo puedo preguntar: ¿el nombre de la columna es realmente ID, en mayúsculas?
NB
Bueno, es más fácil de detectar ahora - katalogtiene int(11) unsigned. spracheno tiene la usignedparte, por lo tanto, dos columnas no son lo mismo.
NB
¿Quiere decir que los dos campos primarios deben ser del mismo tipo de datos?
frgtv10
2
Este es el problema con su diseño: primero, está haciendo referencia a dos auto_incrementcolumnas, lo cual es malo. Además, el manual de MySQL dice: 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.. Por lo tanto, sí, tipo de datos similar y el mismo signo.
NB
2
No estoy haciendo referencia a dos campos auto_increment. katalog.Sprache (no automático) -> sprache.ID (automático)
frgtv10

Respuestas:

560

Para agregar una clave externa (grade_id) a una tabla existente (usuarios), siga los siguientes pasos:

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);
iltaf khalid
fuente
12
Las razones me ayudan a entender y recordar. Esto se debe a que no puede agregar una clave externa a un campo sin signo, ¿correcto?
PixMach
8
@PixMach, la respuesta es no. Puede tener enteros firmados como claves foráneas. Como NB señaló en la pregunta, el tipo y el signo de los campos deben coincidir. Entonces, si su clave principal en la tabla de búsqueda NO ESTÁ FIRMADA, entonces el campo de clave externa también debe NO ESTAR FIRMADO. Si el campo de clave primaria está FIRMADO, entonces el campo de clave externa también debe estar firmado. Piénselo de esta manera: cualquiera que sea la columna en una tabla se define como en SHOW CREATE TABLE, debe tener la misma definición en la otra tabla.
Ben Keene
1
Tenga en cuenta que esto también se podría hacer con una sola consulta (podría ser mejor en caso de falla, etc.)
Stijn de Witt
66
Tuve que ejecutar "SET FOREIGN_KEY_CHECKS = 0;" antes de ejecutar el comando ADD CONSTRAINT o SQL se quejaría "No se puede agregar o actualizar una fila secundaria: falla una restricción de clave externa".
Erin Geyer
2
No , no basta con ejecutar "SET FOREIGN_KEY_CHECKS = 0;" si obtiene el error "falla una restricción de clave externa", obviamente tiene datos incorrectos que debe corregir o de lo contrario obtendrá problemas más grandes en el futuro.
MazeChaZer
72

Simplemente use esta consulta, lo he intentado según mi escenario y funciona bien

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

Pasos simples ...

ALTER TABLE t_name1 ADD FOREIGN KEY (column_name) REFERENCES t_name2(column_name)
Amjath Khan
fuente
15

revisa este enlace. Me ha ayudado con errno 150: http://verysimple.com/2006/10/22/mysql-error-number-1005-cant-create-table-mydbsql-328_45frm-errno-150/

En lo alto de mi cabeza me vienen a la mente dos cosas.

  • ¿Es su índice de clave externa un nombre único en toda la base de datos (# 3 en la lista)?
  • ¿Está tratando de establecer la tabla PK en NULL en la actualización (# 5 en la lista)?

Supongo que el problema es con el conjunto NULL en la actualización (si mis cerebros no están al revés hoy, ya que a menudo son ...).

Editar: me perdí los comentarios en tu publicación original. Las columnas int sin firmar / sin firmar pueden resolver su caso. Espero que mi enlace ayude a alguien en el futuro.

ZZ-bb
fuente
13
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

Pero tu mesa tiene:

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

No puede establecer la columna Sprache en NULL porque se define como NOT NULL.

Cuenta
fuente
5

MySQL ejecutará esta consulta:

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;

¡Salud!

akelec
fuente
5

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

  1. alterar su tabla y agregarle un índice.

    ALTER TABLE users ADD INDEX index_name (index_column)
  2. Ahora agregue la restricción

    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;

Tenga en cuenta que si no agrega un índice, no funcionará.

Después de luchar con él durante aproximadamente 6 horas, encontré la solución, espero que esto salve un alma.

Kwed
fuente
4

Cuando agrega una restricción de clave externa a una tabla usando ALTER TABLE, recuerde crear primero los índices requeridos.

  1. Crear índice
  2. Alterar la mesa
Maksym Polshcha
fuente
Creé índice para ambos. Cuando intento ejecutar me sale el mismo mensaje de error que antes. Cuando rechazo la parte "al eliminar en la actualización" funciona, pero con la acción incorrecta "al eliminar";)
frgtv10
@ frgtv10 es muy probable que los datos de las tablas entren en conflicto con "al eliminar".
Maksym Polshcha
3

intente todo en una consulta

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

Esto sucede básicamente porque sus tablas están en dos conjuntos de caracteres diferentes. Como ejemplo, una tabla creada en charset = utf-8 y otras tablas se crean en CHARSET = latin1, por lo que es posible que pueda agregar una clave extranjera a estas tablas. use el mismo juego de caracteres en ambas tablas, entonces podrá agregar claves extranjeras. error 1005 restricción foriegn clave incorrectamente formada puede resolver a partir de esto

Fernando Pumudu
fuente
0

Pasé por el mismo problema. En mi caso, la tabla ya tiene datos y había claves en esta tabla que no estaban presentes en la tabla de referencia. Así que tuve que eliminar estas filas que no respetan las restricciones y todo funcionó.

Henrique
fuente
0

Paso 1: ejecuta este script

SET FOREIGN_KEY_CHECKS=0;

Paso 2: agregar columna

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

Paso 3: agregue la clave externa a la columna agregada

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

Paso 4: ejecuta este script

SET FOREIGN_KEY_CHECKS=1;
Rushikesh Satpute
fuente
-1
 ALTER TABLE TABLENAME ADD FOREIGN KEY (Column Name) REFERENCES TableName(column name)

Ejemplo:-

ALTER TABLE Department ADD FOREIGN KEY (EmployeeId) REFERENCES Employee(EmployeeId)
Harshitha Nagabhushana
fuente
1
Agregue alguna explicación a su código para que otros puedan aprender de él
Nico Haase