Comment tronquer une table contrainte de clé étrangère?

648

Pourquoi ne pas TRUNCATE sur le mygrouptravail? Même si j'ai, ON DELETE CASCADE SETje reçois:

ERREUR 1701 (42000): impossible de tronquer une table référencée dans une contrainte de clé étrangère ( mytest. instance, RÉFÉRENCES CONSTRAINT instance_ibfk_1FOREIGN KEY ( GroupID) 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;
user391986
la source

Réponses:

1001

Vous ne pouvez pas TRUNCATEune table à laquelle des contraintes FK sont appliquées (ce TRUNCATEn'est pas la même chose queDELETE ).

Pour contourner ce problème, utilisez l'une de ces solutions. Les deux présentent des risques d'endommager l'intégrité des données.

Option 1:

  1. Supprimer les contraintes
  2. Effectuer TRUNCATE
  3. Supprimez manuellement les lignes qui ont maintenant des références à nulle part
  4. Créer des contraintes

Option 2: suggérée par user447951 dans sa réponse

SET FOREIGN_KEY_CHECKS = 0; 
TRUNCATE table $table_name; 
SET FOREIGN_KEY_CHECKS = 1;
zerkms
la source
46
@barjonah: en fait, cela pourrait briser l'intégrité des données (voir stackoverflow.com/questions/5452760/… ). Donc, ce que vous appelez «lumière» dans le monde réel est considéré comme une mauvaise pratique. PS: merci pour le
downvote
1
Voici un très bon moyen de trouver des clés étrangères orphelines (restaurer l'intégrité des données) http://stackoverflow.com/a/12085689/997776
SandorRacz
désactiver la clé étrangère avant de tronquer est également un bon moyen, je l'ai fait avec succès à partir de la source: stackoverflow.com/questions/8641703/…
Dung
2
@Dung, la désactivation des vérifications de clé étrangère n'est autorisée que pendant la période de développement. Il rompt toutes les relations existantes. zerkms a 100% raison sur l'intégrité des données. Vous ne pouvez pas désactiver les vérifications de clé étrangère sur une base de données de travail, sauf si vous prévoyez de la vider complètement (ou au moins toutes les tables associées)
NoobishPro
1
@Kamlesh ce n'est pas ma solution, j'ai conseillé de ne pas le faire de façon barbare.
zerkms
1308

Oui, vous pouvez:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

Avec ces instructions, vous risquez de laisser des lignes dans vos tables qui ne respectent pas les FOREIGN KEYcontraintes.

user447951
la source
30
devons-nous définir SET FOREIGN_KEY_CHECKS = 1; encore après?
vinc3m1
77
Non, non. Le paramètre n'est valide que pendant la connexion. Dès que vous vous déconnectez, la prochaine connexion le ramènera à 1.
Le Pellmeister
7
Cela n'applique pas l'événement 'ON DELETE' dans la table référencée, donc ce n'est pas une réponse complète.
Omer Sabic
5
Si vous utilisez dans PHPMYADMIN, cela ne fonctionne que si vous utilisez toutes les transactions dans la même fenêtre SQL (séparées par un ;). En effet, chaque nouvel appel Web SQL réinitialisera le FOREIGN_KEY_CHECKSà 1.
Sablefoste
1
Voici un très bon moyen de trouver des clés étrangères orphelines (restaurer l'intégrité des données) au cas où vous seriez intéressé http://stackoverflow.com/a/12085689/997776
SandorRacz
173

Je le ferais simplement avec:

DELETE FROM mytest.instance;
ALTER TABLE mytest.instance AUTO_INCREMENT = 1;
George Garchagudashvili
la source
5
Intelligent. De toute façon, si vous souhaitez supprimer tous les enregistrements, vous pouvez aussi réinitialiser l'incrémentation automatique.
winkbrace
6
C'est évidemment la meilleure façon de procéder. Aucun risque de perdre des contraintes, supprimez simplement. Il convient de noter que les DELETEperformances sont plus lentes que TRUNCATE. Mais comme cette action n'est généralement effectuée que rarement, cela n'a pas d'importance.
phil294
C'est bien si c'est tout ce que vous voulez faire, mais DELETEpeut être absolument brutal si vous avez trop de lignes - car il frappe les journaux, alors TRUNCATEqu'il arrache simplement les données. Cela dépend vraiment du cas d'utilisation.
Jeff
1
lorsque j'utilise l'instruction delete, elle signale l'erreur 1175: vous utilisez le mode de mise à jour sécurisé, ajoutez simplement SET SQL_SAFE_UPDATES = 0; alors ça va
tyan
Lors de l'utilisation de cette solution, il signale la error 1175: You are using safe update mode,...modification de la clause de suppression pour la DELETE FROM mydb.mytable where id != 0rendre parfaite.
Shihe Zhang
17

tu peux faire

DELETE FROM `mytable` WHERE `id` > 0
Ali Sadran
la source
1
J'ai essayé, mais l'erreur suivante est apparue: Code d'erreur: 1142. La commande DELETE a été refusée à l'utilisateur 'root' @ 'localhost' pour la table 'mytable'
AAEM
ou simplement SUPPRIMER DEmytable
Miloslav Milo Janoušek
Cela ne réinitialiserait pas l'incrémentation automatique.
vivek_23
13

Selon la documentation mysql , TRUNCATE ne peut pas être utilisé sur des tables avec des relations de clé étrangère. Il n'y a pas d'alternative complète à l'AFAIK.

La suppression de la contraint n'invoque toujours pas ON DELETE et ON UPDATE. La seule solution à laquelle je puisse penser ATM est de:

  • supprimer toutes les lignes, supprimer les clés étrangères, tronquer, recréer les clés
  • supprimer toutes les lignes, réinitialiser auto_increment (si utilisé)

Il semblerait que TRUNCATE dans MySQL ne soit pas encore une fonctionnalité complète (il n'invoque pas non plus de déclencheurs). Voir le commentaire

Omer Sabic
la source
7
Une note sur votre point à propos de MySQL TRUNCATEétant incomplète - tronquer n'est pas censé invoquer des déclencheurs, etc. Si c'était le cas, ce serait la même chose que DELETE! Il est indépendant de la ligne, il est donc incapable d'effectuer des opérations liées à la ligne (comme invoquer des déclencheurs ou examiner des clés étrangères). Il fonctionne de la même manière dans Oracle et Sql Server .
Simon MᶜKenzie
8

Facile si vous utilisez phpMyAdmin.

Décochez simplement l' Enable foreign key checksoption sous l' SQLonglet et exécutezTRUNCATE <TABLE_NAME>

entrez la description de l'image ici

Ajmal Salim
la source
8

Bien que cette question ait été posée, je n'en savais rien, mais maintenant, si vous utilisez phpMyAdmin, vous pouvez simplement ouvrir la base de données et sélectionner la ou les tables que vous souhaitez tronquer.

  • En bas, il y a une liste déroulante avec de nombreuses options. Ouvrez-le et sélectionnez l' Emptyoption sous le titre Delete data or table.
  • Il vous amène automatiquement à la page suivante où il y a une option dans la case à cocher appelée Enable foreign key checks. Il suffit de la désélectionner et d'appuyer sur le Yesbouton et la ou les tables sélectionnées seront tronquées.

Peut-être qu'il exécute en interne la requête suggérée dans la réponse de user447951 , mais il est très pratique à utiliser à partir de l'interface phpMyAdmin.

Rolen Koh
la source
8

Testé sur la base de données MYSQL

Solution 1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;

Solution 2:

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

Cela fonctionne pour moi. J'espère que cela vous aidera aussi. Merci d'avoir posé cette question.

Kamlesh
la source
6

La réponse est en effet celle fournie par les zerkms , comme indiqué dans l' option 1 :

Option 1 : qui ne risque pas de nuire à l'intégrité des données:

  1. Supprimer les contraintes
  2. Effectuer TRONCATE
  3. Supprimez manuellement les lignes qui ont maintenant des références à nulle part
  4. Créer des contraintes

La partie délicate est la suppression des contraintes , donc je veux vous dire comment, au cas où quelqu'un aurait besoin de savoir comment faire:

  1. Exécutez une SHOW CREATE TABLE <Table Name>requête pour voir quel est le nom de votre clé étrangère (cadre rouge dans l'image ci-dessous):

    entrez la description de l'image ici

  2. Courez ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign Key Name>. Cela supprimera la contrainte de clé étrangère.

  3. Supprimez l' index associé (via la page de structure de table) et vous avez terminé.

pour recréer des clés étrangères:

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

Utilisez simplement CASCADE

TRUNCATE "products" RESTART IDENTITY CASCADE;

Mais soyez prêt pour les suppressions en cascade)

Alexus1024
la source
3
L'OP a marqué MySQL. Bien que cela soit valide dans Postgres, il est incorrect dans MySQL.
Peter
1

Si le moteur de base de données pour les tables diffère, vous obtiendrez cette erreur, remplacez-les par InnoDB

ALTER TABLE my_table ENGINE = InnoDB;
sajad abbasi
la source
0

Obtenir l'ancien état de vérification de la clé étrangère et le mode SQL est le meilleur moyen de tronquer / supprimer la table comme le fait Mysql Workbench lors de la synchronisation du modèle avec la base de données.

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
la source