Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

[SOLUCIONADO] Al querer borrar una entrada no puedo

Estas en el tema de Al querer borrar una entrada no puedo en el foro de Mysql en Foros del Web. Quiero borrar una entrada en una tabla de mi BD. El problema es que al hacerlo me indica lo siguiente Cita: Cannot delete or update ...
  #1 (permalink)  
Antiguo 14/12/2013, 08:32
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 11 años, 5 meses
Puntos: 84
Al querer borrar una entrada no puedo

Quiero borrar una entrada en una tabla de mi BD.

El problema es que al hacerlo me indica lo siguiente

Cita:
Cannot delete or update a parent row: a foreign key constraint fails (`admin`.`answers`, CONSTRAINT `answers_ibfk_1` FOREIGN KEY (`id_questions`) REFERENCES `questions` (`id_question`))
Entonces al leer en el manual de MYSQL sobre constraints no me ha quedado claro qué tengo que hacer para evitar este error. Me cuesta entenderlo.

No entiendo cómo tengo un constraint si cuando creé la tabla no la indiqué, supongo que fue cosa de PHPMyadmin. Hice un show create table y esto es lo que me mostró

Código SQL:
Ver original
  1. CREATE TABLE `questions` (
  2.   `id_question` INT(11) NOT NULL AUTO_INCREMENT,
  3.   `question` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_spanish2_ci NOT NULL,
  4.   `id_typequestions` INT(11) NOT NULL,  PRIMARY KEY (`id_question`),
  5.   KEY `id_typequestions` (`id_typequestions`),  CONSTRAINT `questions_ibfk_1` FOREIGN KEY (`id_typequestions`) REFERENCES `typequestions` (`id_typequestion`))
  6.  ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8

Como se puede apreciar, en la 5ª línea hay un constraint.

¿Alguien puede ayudarme a entender los constraints y a solucionar este problema?
__________________
Ayúdame a hacerlo por mi mismo.
  #2 (permalink)  
Antiguo 14/12/2013, 08:55
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Al querer borrar una entrada no puedo

No estás leyendo bien el mensaje del error:
Cita:
a foreign key constraint fails (`admin`.`answers`, CONSTRAINT `answers_ibfk_1` FOREIGN KEY (`id_questions`) REFERENCES `questions` (`id_question`))
El problema no es que tengas una FK en la tabla answers, sino que otra tabla apunta a answers, por lo tanto no puedes borrar una respuesta si está siendo usada como FK en otra tabla.

Habría que revisar las relaciones entre las tablas para ver si no han quedado dependencias mal construidas.
En cualquier caso, la respuesta es simple.

Supongamos que tienes este tipo de relación:
Cita:
A -> B -> C
No puedes borrar C, porque B depende de ella, ni borrar B, porque A depende de B.
Para borrar C, entonces, debes borrar primero A que se relacione con B y donde exista relación con C.
Luego debes borrar los B relacionados con C. Y sólo entonces puedes borrar C.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 14/12/2013, 09:27
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 11 años, 5 meses
Puntos: 84
Respuesta: Al querer borrar una entrada no puedo

Ahhhhh ahora sí entiendo. Tu ejemplo con A->B->C me resultó clarificador.

No había caído en que answers tiene una foreign key de questions y esta a su vez tiene una foreign key de typequestions.

Para poder borrar una question tengo que borrar una answer, absolutamente lógico.

Lo mismo con typequestions.

Mi torpeza no tiene límites.

Muchas gracias gnzsoloyo!!!
__________________
Ayúdame a hacerlo por mi mismo.
  #4 (permalink)  
Antiguo 14/12/2013, 11:22
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 11 años, 5 meses
Puntos: 84
Respuesta: Al querer borrar una entrada no puedo

He seguido estas indicaciones que he encontrado, son tuyas :D , pero no lo logro.

Así ha quedado el SQL (el 14 en realidad sería una variable de PHP)

Código SQL:
Ver original
  1. DELETE questions FROM questions
  2.                     INNER JOIN answers USING (id_questions)
  3.                     WHERE questions.id_question = 14;

me dice el siguiente error

Cita:
Unknown column 'id_questions' in 'from clause'
No entiendo por qué el DELETE tiene después el nombre de la tabla y después del FROM otra vez el nombre de la tabla :S

Si quito el nombre de la tabla después del DELETE me dice este error

Cita:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INNER JOIN answers USING (id_questions) WHERE questions.id_que' at line 2
__________________
Ayúdame a hacerlo por mi mismo.
  #5 (permalink)  
Antiguo 14/12/2013, 11:54
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Al querer borrar una entrada no puedo

"id_questions" es el nombre de la columna enla tabla "questions", pero... ¿se llama así también en "answers"?
La cláusula USING sólo funciona si la columna relacional tiene el mismo nombre en ambas tablas. Por eso precisamente se considera buena práctica que los nombres de la columnas que son FK tengan exactamente la misma denominación que sus campos de origen.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #6 (permalink)  
Antiguo 14/12/2013, 12:26
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 11 años, 5 meses
Puntos: 84
Respuesta: Al querer borrar una entrada no puedo

Cita:
Iniciado por gnzsoloyo Ver Mensaje
"id_questions" es el nombre de la columna enla tabla "questions", pero... ¿se llama así también en "answers"?
La cláusula USING sólo funciona si la columna relacional tiene el mismo nombre en ambas tablas. Por eso precisamente se considera buena práctica que los nombres de la columnas que son FK tengan exactamente la misma denominación que sus campos de origen.
id_questions es el nombre en la tabla answers, en la tabla questions es id_question.

ahora intento modificar la columna hija en answers con lo siguiente y me da error (probé con el propio PHPMyadmin pero no me deja hacerlo, me da error también)

Código SQL:
Ver original
  1. ALTER TABLE answers CHANGE id_questions id_question INTEGER NOT NULL;

es en el remoto, por desgracia no puedo utilizar MYSQL Workbench, es por eso que tengo que trabajar en "modo manual".
__________________
Ayúdame a hacerlo por mi mismo.
  #7 (permalink)  
Antiguo 14/12/2013, 14:09
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Al querer borrar una entrada no puedo

Probemos:
Código MySQL:
Ver original
  1. DELETE a, q
  2. FROM questions q  INNER JOIN answers a ON q.id_question = a.id_questions
  3. WHERE q.id_question = 14;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #8 (permalink)  
Antiguo 14/12/2013, 14:42
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 11 años, 5 meses
Puntos: 84
Respuesta: Al querer borrar una entrada no puedo

Nada, me devuelve el primer error. He vuelto a intentar cambiar el nombre de la columna, pero no me deja, erre que erre.
__________________
Ayúdame a hacerlo por mi mismo.
  #9 (permalink)  
Antiguo 14/12/2013, 15:38
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Al querer borrar una entrada no puedo

No te permite cambiarle el nombre por un problema en el manejo interno de MySQL para ese caso: No cambia el nombre, sino que crea una columna con el nombre nuevo, copia los datos y trata de borrar la vieja columna. Entonces, en los hechos es lo mismo que intentar dropearla: No te dejará porque violaría la restricción de FK.
Empecemos por mirar lo que dices en un momento:
Cita:
No había caído en que answers tiene una foreign key de questions y esta a su vez tiene una foreign key de typequestions.
Se supone que en ese contexto lo que hay que hacer es borrar answers antes de questions. Lo que resulta difícil (y eso lo aclara el manual) es hacerlo usando JOIN, porque MySQL no lee la dependencia, sino que intenta realizar el borrado en base a un plan calculado on the fly, y puede estar haciéndolo al revés.
Ahora bien, para hacerte simple la tarea, hagamos esto: Agregale un ON DELETE CASCADE ON UPDATE CASCADE a la FK de answers.
Básicamente es eliminar la FK y volverla a crear. Luego de que lo hagas, si borras questions, se borrarán solas las answers dependientes.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 14/12/2013 a las 18:22
  #10 (permalink)  
Antiguo 14/12/2013, 18:20
Avatar de guardarmicorreo  
Fecha de Ingreso: noviembre-2012
Ubicación: Córdoba
Mensajes: 1.153
Antigüedad: 11 años, 5 meses
Puntos: 84
Respuesta: Al querer borrar una entrada no puedo

Te he hecho caso y me funcionó :D

Voy a contar cómo he podido hacerlo para que quede para la posteridad xD ya que la verdad es que me ha costado poder hacerlo.

Primero tuve que hacer un show create table con la finalidad de poder ver el 'ibfk_número'.
Ese es el constraint, el cual hay que borrarlo.

Así que lo siguiente es borrar dicho constraint

Código SQL:
Ver original
  1. ALTER TABLE answers DROP FOREIGN KEY answers_ibfk_1

Después hay que volver a crear el constraint pero hay que crearlo con el ON DELETE CASCADE

Código SQL:
Ver original
  1. ALTER TABLE answers ADD FOREIGN KEY (id_questions) REFERENCES questions (id_question) ON DELETE CASCADE;

Y finalmente puedo borrar entradas con referencias en otra tabla.

En mi caso la sentencia SQL quedó así

Código SQL:
Ver original
  1. DELETE a, q
  2. FROM questions q  INNER JOIN answers a ON q.id_question = a.id_questions
  3. WHERE q.id_question =14;

La advertencia es que con ON DELETE CASCADE añadido, al borrar una entrada padre, las entradas hijas en otra tabla serán borradas. En mi caso es exactamente lo que necesito, ya que no puede haber respuestas sin preguntas.

Gracias gnzsoloyo!!! otro conocimiento adquirido gracias a ti! :D
__________________
Ayúdame a hacerlo por mi mismo.
  #11 (permalink)  
Antiguo 14/12/2013, 18:23
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Al querer borrar una entrada no puedo

__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Etiquetas: entrada, null, php, sql, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:07.