¿Cómo truncar una tabla restringida de clave externa?

648

¿Por qué un TRUNCADO no mygroupfunciona? Aunque tengo ON DELETE CASCADE SETtengo:

ERROR 1701 (42000): No se puede truncar una tabla de referencia en una restricción de clave externa ( mytest. instance, La restricción de instance_ibfk_1clave externa ( GroupID) REFERENCIAS mytest. mygroup( ID))

drop database mytest;
create database mytest;
use mytest;

CREATE TABLE mygroup (
   ID    INT NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;

CREATE TABLE instance (
   ID           INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
   GroupID      INT NOT NULL,
   DateTime     DATETIME DEFAULT NULL,

   FOREIGN KEY  (GroupID) REFERENCES mygroup(ID) ON DELETE CASCADE,
   UNIQUE(GroupID)
) ENGINE=InnoDB;
usuario391986
fuente

Respuestas:

1001

No puede TRUNCATEuna tabla que tenga restricciones FK aplicadas ( TRUNCATEno es lo mismo que DELETE).

Para evitar esto, use cualquiera de estas soluciones. Ambos presentan riesgos de dañar la integridad de los datos.

Opción 1:

  1. Eliminar restricciones
  2. Realizar TRUNCATE
  3. Eliminar manualmente las filas que ahora tienen referencias a ninguna parte
  4. Crear restricciones

Opción 2: sugerida por el usuario 447951 en su respuesta

SET FOREIGN_KEY_CHECKS = 0; 
TRUNCATE table $table_name; 
SET FOREIGN_KEY_CHECKS = 1;
zerkms
fuente
46
@barjonah: en realidad, podría romper la integridad de los datos (consulte stackoverflow.com/questions/5452760/… ). Entonces, lo que llamas "luz" en el mundo real se considera una mala práctica. PD: gracias por el
voto negativo
1
Aquí hay una muy buena manera de encontrar claves foráneas huérfanas (restaurar la integridad de los datos) http://stackoverflow.com/a/12085689/997776
SandorRacz
deshabilitar la clave externa antes de truncar también es una buena manera, lo hice con éxito desde la fuente: stackoverflow.com/questions/8641703/…
Dung
2
@Dung deshabilitar las comprobaciones de clave externa solo está permitido en el período de desarrollo. Rompe cualquier relación existente. zerkms tiene 100% de razón sobre la integridad de los datos. No puede deshabilitar las comprobaciones de claves externas en una base de datos en funcionamiento a menos que esté planeando vaciarla completamente (o al menos todas las tablas relacionadas)
NoobishPro
1
@Kamlesh no es mi solución, aconsejé no hacerlo de esa manera bárbara.
zerkms
1308

Sí tu puedes:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

Con estas declaraciones, corre el riesgo de dejar filas en sus tablas que no cumplan con las FOREIGN KEYrestricciones.

usuario447951
fuente
30
¿tenemos que establecer SET FOREIGN_KEY_CHECKS = 1; de nuevo después?
vinc3m1
77
No, tu no. La configuración solo es válida durante la conexión. Tan pronto como se desconecte, la próxima conexión lo
restablecerá
77
Esto no aplica el evento 'ON DELETE' en la tabla referenciada, por lo que esta no es una respuesta completa.
Omer Sabic
55
Si se usa en PHPMYADMIN, esto solo funciona si usa todas las transacciones en la misma ventana SQL (separadas por a ;). Esto se debe a que cada nueva llamada SQL web restablecerá el FOREIGN_KEY_CHECKS1.
Sablefoste
1
Aquí hay una muy buena manera de encontrar claves foráneas huérfanas (restaurar la integridad de los datos) en caso de que esté interesado http://stackoverflow.com/a/12085689/997776
SandorRacz
173

Simplemente lo haría con:

DELETE FROM mytest.instance;
ALTER TABLE mytest.instance AUTO_INCREMENT = 1;
George Garchagudashvili
fuente
55
Inteligente. Cuando quiera eliminar todos los registros de todos modos, también puede restablecer el incremento automático.
winkbrace
66
Obviamente, esta es la mejor manera de hacerlo. No hay riesgo de perder restricciones, simplemente borre. Vale la pena notar que DELETEfunciona más lento que TRUNCATE. Pero dado que esta acción generalmente se realiza solo en raras ocasiones, esto no importa.
phil294
Esto es bueno si eso es todo lo que quiere hacer, pero DELETEpuede ser absolutamente brutal si tiene demasiadas filas, ya que golpea los registros, mientras que TRUNCATEsimplemente elimina los datos. Realmente depende del caso de uso.
Jeff
1
cuando estoy usando la instrucción delete, informa el error 1175: Estás usando el modo de actualización segura, solo agrega SET SQL_SAFE_UPDATES = 0; entonces está bien
tyan
Cuando se utiliza esta solución, informa la error 1175: You are using safe update mode,...cláusula de cambio de eliminación para DELETE FROM mydb.mytable where id != 0que sea perfecta.
Shihe Zhang
17

tu puedes hacer

DELETE FROM `mytable` WHERE `id` > 0
Ali Sadran
fuente
1
Lo intenté, apareció el siguiente error: Código de error: 1142. El comando DELETE fue denegado al usuario 'root' @ 'localhost' para la tabla 'mytable'
AAEM
o simplemente ELIMINARmytable
Miloslav Milo Janoušek
Esto no restablecería el incremento automático.
vivek_23
13

Según la documentación de mysql , TRUNCATE no se puede usar en tablas con relaciones de clave externa. No existe una alternativa completa AFAIK.

Dejar caer la restricción todavía no invoca ON DELETE y ON UPDATE. La única solución que puedo pensar en ATM es:

  • eliminar todas las filas, soltar las claves foráneas, truncar, recrear claves
  • eliminar todas las filas, restablecer auto_increment (si se usa)

Parece que TRUNCATE en MySQL aún no es una característica completa (tampoco invoca disparadores). Ver comentario

Omer Sabic
fuente
77
Una nota sobre su punto acerca de que MySQL TRUNCATEestá incompleto: no se supone que truncar invoque desencadenantes, etc. Si lo hiciera, ¡sería lo mismo DELETE! Es independiente de las filas, por lo tanto, no puede realizar operaciones relacionadas con las filas (como invocar desencadenantes o examinar claves externas). Funciona de la misma manera en Oracle y SQL Server .
Simon MᶜKenzie
8

Fácil si estás usando phpMyAdmin.

Simplemente desmarque la Enable foreign key checksopción en la SQLpestaña y ejecuteTRUNCATE <TABLE_NAME>

ingrese la descripción de la imagen aquí

Ajmal Salim
fuente
8

Si bien se hizo esta pregunta, no lo sabía, pero ahora si usa phpMyAdmin, simplemente puede abrir la base de datos y seleccionar las tablas que desea truncar.

  • En la parte inferior hay un menú desplegable con muchas opciones. Ábralo y seleccione la Emptyopción debajo del encabezado Delete data or table.
  • Te lleva a la siguiente página automáticamente donde hay una opción en la casilla de verificación llamada Enable foreign key checks. Simplemente anule la selección y presione el Yesbotón y las tablas seleccionadas se truncarán.

Tal vez internamente ejecuta la consulta sugerida en la respuesta del usuario 447951 , pero es muy conveniente usarla desde la interfaz phpMyAdmin.

Rolen Koh
fuente
8

Probado en la base de datos MYSQL

Solución 1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;

Solución 2:

DELETE FROM table1;
ALTER TABLE table1 AUTO_INCREMENT = 1;
TRUNCATE table1;

Esto funciona para mi. Espero que esto también te ayude. Gracias por hacer esta pregunta.

Kamlesh
fuente
6

La respuesta es de hecho la proporcionada por zerkms , como se indica en la Opción 1 :

Opción 1 : que no corre el riesgo de dañar la integridad de los datos:

  1. Eliminar restricciones
  2. Realizar TRUNCATE
  3. Eliminar manualmente las filas que ahora tienen referencias a ninguna parte
  4. Crear restricciones

La parte difícil es eliminar restricciones , por lo que quiero decirte cómo, en caso de que alguien necesite saber cómo hacerlo:

  1. Ejecute la SHOW CREATE TABLE <Table Name>consulta para ver cuál es el nombre de su CLAVE EXTRANJERA (marco rojo en la imagen de abajo):

    ingrese la descripción de la imagen aquí

  2. Ejecutar ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign Key Name>. Esto eliminará la restricción de clave externa.

  3. Suelte el índice asociado (a través de la página de estructura de la tabla) y listo.

para volver a crear claves foráneas:

ALTER TABLE <Table Name>
ADD FOREIGN KEY (<Field Name>) REFERENCES <Foreign Table Name>(<Field Name>);
Pmpr
fuente
3

Solo usa CASCADE

TRUNCATE "products" RESTART IDENTITY CASCADE;

Pero prepárate para borrados en cascada)

Alexus1024
fuente
3
El OP etiquetado MySQL. Si bien esto es válido en Postgres, es incorrecto en MySQL.
Peter
1

Si el motor de la base de datos para tablas difiere, obtendrá este error, así que cámbielo a InnoDB

ALTER TABLE my_table ENGINE = InnoDB;
sajad abbasi
fuente
0

Obtener el antiguo estado de verificación de clave externa y el modo sql son la mejor manera de truncar / soltar la tabla como lo hace Mysql Workbench mientras se sincroniza el modelo con la base de datos.

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;`
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

DROP TABLE TABLE_NAME;
TRUNCATE TABLE_NAME;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
Vijay Arun
fuente