No se puede agregar o actualizar una fila secundaria: falla una restricción de clave externa

174

tabla 1

+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| UserID   | int(11)     | NO   | PRI | NULL    | auto_increment |
| Password | varchar(20) | NO   |     |         |                |
| Username | varchar(25) | NO   |     |         |                |
| Email    | varchar(60) | NO   |     |         |                |
+----------+-------------+------+-----+---------+----------------+

Tabla 2

+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| UserID           | int(11)      | NO   | MUL |         |                |
| PostID           | int(11)      | NO   | PRI | NULL    | auto_increment |
| Title            | varchar(50)  | NO   |     |         |                |
| Summary          | varchar(500) | NO   |     |         |                |
+------------------+--------------+------+-----+---------+----------------+

Error:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: 
Cannot add or update a child row: a foreign key constraint fails 
(`myapp/table2`, CONSTRAINT `table2_ibfk_1` FOREIGN KEY (`UserID`) 
REFERENCES `table1` (`UserID`)) 

¿Qué he hecho mal? Leí http://www.w3schools.com/Sql/sql_foreignkey.asp y no veo qué pasa.

Tom
fuente
44
¿Puedes publicar la consulta que desencadena el error?
Húmedo
38
En pocas palabras, está intentando insertar / actualizar un valor table2.UserIDque no existe en table1.UserID.
Joe Stefanelli
No estoy seguro de por qué, pero después de mover mi base de datos de un entorno de Windows a Linux, tuve que eliminar y volver a crear una relación (fue entonces cuando noté el problema). El valor existía, pero al eliminar y volver a agregar la relación, se solucionó. Es posible que tenga que tener mucho cuidado al hacerlo, obviamente.
johnsnails

Respuestas:

235

Obtiene este error porque está intentando agregar / actualizar una fila table2que no tiene un valor válido para el UserIDcampo en función de los valores almacenados actualmente table1. Si publicas más código, puedo ayudarte a diagnosticar la causa específica.

Brian Driscoll
fuente
PreparedStatement st = connection.prepareStatement ("Insertar en la tabla2 (ID de usuario, PostID, Título, Resumen)" + "valores (ID de usuario,?,?,?)");
Tom
15
no estoy seguro de para qué sirve el voto negativo; Mi respuesta es perfectamente válida y correcta.
Brian Driscoll
Hmm ... definitivamente no es una buena idea mezclar parámetros con nombre con parámetros sin nombre en su declaración preparada. debe ser "valores (?,?,?,?)" con el valor apropiado para el ID de usuario especificado en su instrucción de ejecución.
Brian Driscoll
¿Entonces necesito hacer otra instrucción SQL para obtener el ID de usuario de la tabla1?
Tom
55
Lo más probable es un 0, reemplácelo por Null si es el caso
Jeffrey Nicholson Carré
123

Significa que está intentando insertar en table2un UserIDvalor que no existe table1.

Rami C
fuente
104

Un truco simple puede ser desactivar las comprobaciones de clave externa antes de realizar cualquier operación en la tabla. Simplemente consulta

SET FOREIGN_KEY_CHECKS=0

Esto deshabilitará la coincidencia de claves foráneas con cualquier otra tabla. Una vez que haya terminado con la tabla, vuelva a habilitarla

SET FOREIGN_KEY_CHECKS=1

Esto me funciona muchas veces.

Sandeep Giri
fuente
¿Cómo uso esto?
Sachin de Pune el
2
@SachinfromPune solo agrega SET FOREIGN_KEY_CHECKS = 0; al inicio del archivo mysql y SET FOREIGN_KEY_CHECKS = 1; al final del archivo mysql, reimportar datos
inrsaurabh
1
¿No es esto problemático? Pierdes integridad referencial, ¿verdad?
roadrunner66
La integridad referencial está respaldada por la presencia de las entradas de índice correctas. Siempre que tenga sus claves e índices correctos, debería poder desactivar la verificación de claves durante una entrada masiva.
Vernon Keenan
46

Descubrí otro caso extraño: si accidentalmente crea una clave foránea desde una tabla InnoDB a una tabla MyISAM, MySQL arroja este error al momento de la inserción, incluso si los datos son válidos.

Ver http://nick.zoic.org/art/mysql-foreign-key-error/

NickZoic
fuente
1
Sí, tengo el mismo problema. ¡Dos tablas deberían ser InnoDB!
emeraldhieu
2
Tuve el mismo problema, gracias por el consejo. Aquí hay un enlace a la documentación de MySQL sobre cómo convertir las tablas de MyISAM a InnoDB dev.mysql.com/doc/refman/5.7/en/... TLDR: ALTER TABLE nombre_tabla ENGINE = InnoDB;
Guilherme Vaz
De hecho, este fue el caso en mi base de datos. Decidí cambiar el motor MyISAM a InnoDB. Finalmente, puedo trabajar con la base de datos de la manera que quería.
Mike
17

Obtiene este error porque hay algún valor int table2.UserIDque no existe table1.UserID(supongo que ha establecido el table2.UserIDvalor manualmente antes de crear esta clave foránea).
Un ejemplo para esta escena: table1.UserIDobtener los valores 1,2,3 y table2.UserIDobtener los valores 4 (agregar por manual). Así que cuando usted hace una clave externa, que no pueden encontrar UserID = 4a partir table1y el error será ocurse.
Para solucionar este error, acaba de quitar UserID = 4de table2o puede vaciar ambos y luego crear la clave externa y.
¡Buena suerte!

Justin
fuente
11

Esto me llevó un tiempo darme cuenta. En pocas palabras, la tabla que hace referencia a la otra tabla ya tiene datos y uno o más de sus valores no existen en la tabla principal.

por ejemplo, Table2 tiene los siguientes datos:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

Tabla 1

UserID    Password    Username    Email
9         ********    JohnDoe     john@example.com

Si intenta ALTERAR table2 y agrega una clave foránea, la consulta fallará porque UserID = 5 no existe en Table1.

Sbudah
fuente
10

Si ha insertado una fila en la tabla 1 antes de crear la clave externa en la tabla 2, obtendrá un error de restricción de clave externa, porque el valor de incremento automático es 2 en la tabla 1 y 1 en la tabla 2. Para resolver esto, debe truncar la tabla 1 y volver a establecer el valor de incremento automático en 1. Luego puede agregar la tabla 2.

Attaque
fuente
10

Asegúrese de haber configurado el motor de base de datos en InnoDB porque en MyISAM la clave externa y la transacción no son compatibles

Aman Maurya
fuente
2
ALTER TABLE my_table ENGINE = InnoDB;
Bishwas Mishra
7

Solo una pequeña solución: haga que JoinColumn 'nullable = true' en Table1 y el campo 'UserID' 'insertable = false' y 'nullable = true' en Table2.

En la entidad Table1:

@OneToMany(targetEntity=Table2.class, cascade = CascadeType.ALL)
@JoinColumn(name = "UserID", referencedColumnName = "UserID", nullable = true)
private List<Table2> table2List;

En la entidad Table2:

@Column(insertable = false, nullable = true)
private int UserID;
Ujjwal Chaudhary
fuente
Esta respuesta resolvió totalmente mi problema, muchas gracias por compartir esto. La clave para mí fue agregar @Column (insertable = false, nullable = true) en el archivo que estoy usando como clave de búsqueda en mi objeto / tabla secundaria.
Israelm
6

Acabo de tener el mismo problema, la solución es fácil.

Está intentando agregar una identificación en la tabla secundaria que no existe en la tabla primaria.

compruebe bien, porque InnoDB tiene el error que a veces aumenta la columna auto_increment sin agregar valores, por ejemplo, INSERT ... ON DUPLICATE KEY

Blaztix
fuente
¿seriamente? no inserte una referencia de identificación que no existe ... solo verifique
Blaztix
5

Tuve un problema similar. Está intentando aplicar una clave foránea en una tabla que tiene contenido y la columna no es anulable. Tienes dos opciones.

  1. Haga que la columna en la que desea aplicar restricciones de clave externa sea anulable. De esa manera, la clave externa se aplicará sabiendo que algunos campos pueden ser anulables. ( Esto es lo que hice )
  2. Cree la columna a la que desea aplicar la restricción de clave externa, escriba una consulta para insertar la clave externa en la columna y luego aplique las restricciones de clave externa. ( No probé esto pero debería funcionar )
Jacob
fuente
4

Asegúrese de que el valor que está insertando en la clave externa exista en la tabla primaria. Eso me ayudo. Por ejemplo, si inserta user_id = 2en table.2, pero table.1no tiene un user_id = 2, entonces la restricción arrojará un error. El mío fue el código de error # 1452 para ser exactos. ¡Espero que esto ayude a alguien más con el mismo problema!

Dustin Hammack
fuente
3

Tuve el mismo problema, y ​​la razón fue que tuve una fila en la primera tabla antes de agregar la clave foránea.

Ouissal
fuente
1

También enfrenté el mismo problema y el problema era que el valor de las entradas de la tabla principal no coincidía con el valor de la tabla de clave externa. Así que por favor intente después de borrar todas las filas ...

Justin jose
fuente
La restricción requiere que los usuarios a los que se hace referencia en la Tabla2 ya estén definidos en la Tabla1.
sorak
1

En caso de que las soluciones proporcionadas por otros no funcionen. Entonces debería intentar verificar los motores de base de datos de las tablas principal y secundaria. En mi caso, tenía el motor de las tablas principales configurado en "MyISAM", cambiándolo a InnoDB.

Espero que esto ayude a otros que están atrapados como yo.

Arun Shankar
fuente
1

No debe colocar un campo ondelete contra una cascada en la base de datos.

Establezca el campo onDelete en RESTRICT

Buena suerte ♥

HamidReza Biglari
fuente
0

Otro caso extraño que me dio este error. Había hecho referencia errónea a mis claves foráneas a la clave primaria id. Esto fue causado por comandos incorrectos de alterar tabla. Descubrí esto al consultar la tabla INFORMATION_SCHEMA (Ver esta respuesta de stackoverflow)

La tabla estaba tan confundida que no podía ser reparada por ningún comando ALTER TABLE . Finalmente dejé caer la mesa y la reconstruí. Esto eliminó la integridadError.

Vicky T
fuente
0

Tal vez mientras agrega la userIDcolumna, hay datos para esa determinada tabla que está establecida, por lo que tendrá un valor predeterminado de 0, intente agregar la columna sin elNOT NULL

WTFZane
fuente
0

También recibí este error: "No se puede agregar o actualizar una fila secundaria: falla una restricción de clave externa". Recibí el error al agregar una nueva fila a la tabla primaria

El problema era que la restricción de clave externa se había definido en la tabla primaria en lugar de la tabla secundaria.

Nadir Latif
fuente
0

Si usa el índice mysql o la relación entre tablas, primero elimina las columnas (por ejemplo: city_id) y crea nuevas columnas con el mismo nombre (por ejemplo: city_id). Luego intente nuevamente ...

Mahmut Aydın
fuente
0

¿Hay algún dato existente que contenga la tabla? Si es así, intente borrar todos los datos en la tabla que desea agregar una clave foránea. Luego, ejecute el código (agregue una clave foránea) nuevamente.

Encontré este problema muchas veces. Esta eliminación de todos los datos de la tabla funciona cuando desea agregar una clave externa en una tabla existente.

Espero que esto funcione :)

Noldy
fuente
0

Eliminar índices del campo ID de usuario de table2. Sus trajes para mi

Anton
fuente
-1

la restricción de clave externa de la tabla secundaria falla

Este problema puede surgir debido a la siguiente razón:

Si lo está haciendo en Spring mvc, debe describir explícitamente el tipo de identificación, porque a veces mysql no reconoce el tipo de identificación. así que estableces explícitamente como en ambas tablas en tu clase de entidad@GeneratedValue (strategy = GenerationType.IDENTITY)

Qaiser Iqbal Moeeni
fuente