Quel est le meilleur moyen de vider une table MySQL auto-référentielle?
-
03-07-2019 - |
Question
J'ai une table MySQL auto-référentielle avec un parent_id récursif:
CREATE TABLE `recursive` (
`id` int(11) NOT NULL auto_increment,
`parent_id` int(11) default NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `data_categorysource_parent_id` (`parent_id`),
CONSTRAINT `parent_id_refs_id_627b4293`
FOREIGN KEY (`parent_id`) REFERENCES `data_categorysource` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Pendant les tests, je souhaite le vider, mais échec de TRUNCATE:
TRUNCATE `recursive`
/* SQL Error: Cannot delete or update a parent row: a foreign key
constraint fails...
Je dois actuellement supprimer manuellement tous les enregistrements, en commençant par le bas de l'arborescence, en commençant par le haut. Cela devient difficile même avec de petits arbres.
Y at-il un moyen facile de contourner cela? Je ne peux pas DROP
la table et la recréer facilement, car d'autres tables la référencent (j'ai déjà tronqué celles-ci, il ne devrait donc y avoir aucun problème d'intégrité des données).
La solution
Pourquoi pas:
UPDATE 'recursive' SET 'parent_id' = NULL WHERE 'parent_id' IS NOT NULL;
DELETE FROM 'recursive';
?
Autres conseils
Si vous souhaitez simplement vider l'ensemble du contenu à des fins de test, utilisez:
SET FOREIGN_KEY_CHECKS = 0;
// Execute Query
SET FOREIGN_KEY_CHECKS = 1;
Ceci contourne totalement les vérifications de clé étrangère.
Eh bien, vous pouvez ajouter un ON DELETE CASCADE
à la FOREIGN KEY
définition ... au moins temporairement. Cela vous permettrait de tronquer la table en supprimant d’abord les lignes référencées.
Il existe d'autres ON DELETE
les types aussi; la valeur par défaut est ON DELETE NO ACTION
.
Ou simplement supprimer la contrainte de clé étrangère (récursive), puis tronquer la table, puis rajouter la contrainte.
Sélectionnez à plusieurs reprises les lignes qui n'apparaissent pas en tant que parents et supprimez-les jusqu'à ce que le tableau soit vide. (En supposant qu'il n'y ait pas de cycles ...)
supprimer de la table_1 où date (table_1_TIME) < (sélectionnez T.t_Date à partir de (sélectionnez max (date (table_1_TIME)) en tant que t_Date de la table_1) en tant que T)