Come troncare una tabella vincolata con chiave esterna?


648

Perché non fa un TRUNCATE sul mygrouplavoro? Anche se ON DELETE CASCADE SETho ricevuto:

ERRORE 1701 (42000): impossibile troncare una tabella a cui fa riferimento un vincolo di chiave esterna ( mytest. instance, CONSTRAINT instance_ibfk_1FOREIGN KEY ( GroupID) REFERENCES 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;

Risposte:


1001

Non è possibile TRUNCATEuna tabella a cui sono applicati vincoli FK ( TRUNCATEnon è la stessa di DELETE).

Per ovviare a questo, utilizzare una di queste soluzioni. Entrambi presentano rischi di danneggiare l'integrità dei dati.

Opzione 1:

  1. Rimuovi i vincoli
  2. Eseguire TRUNCATE
  3. Elimina manualmente le righe che ora hanno riferimenti al nulla
  4. Crea vincoli

Opzione 2: suggerito dall'utente447951 nella sua risposta

SET FOREIGN_KEY_CHECKS = 0; 
TRUNCATE table $table_name; 
SET FOREIGN_KEY_CHECKS = 1;

46
@barjonah: in realtà, potrebbe compromettere l'integrità dei dati (consultare stackoverflow.com/questions/5452760/… ). Quindi, ciò che chiami "luce" nel mondo reale è considerato una cattiva pratica. PS: grazie per il downvote
zerkms

1
Ecco un ottimo modo per trovare chiavi esterne orfane (ripristinare l'integrità dei dati) http://stackoverflow.com/a/12085689/997776
SandorRacz

disabilitare la chiave esterna prima di troncare è anche un buon modo, l'ho fatto con successo dalla fonte: stackoverflow.com/questions/8641703/…
Dung

2
@Dung disabilitando i controlli di chiave esterna è consentito solo nel periodo di sviluppo. Rompe qualsiasi relazione esistente. zerkms ha ragione al 100% sull'integrità dei dati. Non è possibile disabilitare i controlli delle chiavi esterne su un database funzionante a meno che non si
preveda

1
@Kamlesh non è la mia soluzione, ho consigliato di non farlo in modo barbaro.
zerkms,

1308

Si, puoi:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

Con queste affermazioni, si rischia di inserire righe nelle tabelle che non aderiscono ai FOREIGN KEYvincoli.


30
dobbiamo impostare SET FOREIGN_KEY_CHECKS = 1; ancora dopo?
vinc3m1,

77
No, non lo fai. L'impostazione è valida solo durante la connessione. Non appena ti disconnetti, la connessione successiva verrà ripristinata a 1.
The Pellmeister,

7
Questo non applica l'evento 'ON DELETE' nella tabella referenziata, quindi questa non è una risposta completa.
Omer Sabic,

5
Se si utilizza in PHPMYADMIN, funziona solo se si utilizzano tutte le transazioni nella stessa finestra SQL (separate da una ;). Questo perché ogni nuova chiamata SQL web reimposterà FOREIGN_KEY_CHECKSsu 1.
Sablefoste

1
Ecco un ottimo modo per trovare chiavi esterne orfane (ripristinare l'integrità dei dati) nel caso in cui tu sia interessato http://stackoverflow.com/a/12085689/997776
SandorRacz

173

Lo farei semplicemente con:

DELETE FROM mytest.instance;
ALTER TABLE mytest.instance AUTO_INCREMENT = 1;

5
Inteligente. Se si desidera eliminare comunque tutti i record, è possibile anche ripristinare l'incremento automatico.
winkbrace,

6
Questo è ovviamente il modo migliore per farlo. Nessun rischio di perdere vincoli, basta semplicemente eliminare. Vale la pena notare che DELETEfunziona più lentamente di TRUNCATE. Ma poiché questa azione viene di solito eseguita solo raramente, questo non ha importanza.
phil294,

Questo è buono se è tutto ciò che vuoi fare, ma DELETEpuò essere assolutamente brutale se hai troppe righe, poiché colpisce i log, mentre TRUNCATEstrappa i dati. Dipende molto dal caso d'uso.
Jeff,

1
quando sto usando l'istruzione delete, riporta l'errore 1175: stai usando la modalità di aggiornamento sicuro, basta aggiungere SET SQL_SAFE_UPDATES = 0; allora va bene
tyan

Quando si utilizza questa soluzione, segnala la error 1175: You are using safe update mode,...clausola di eliminazione delle modifiche per DELETE FROM mydb.mytable where id != 0renderla perfetta.
Shihe Zhang,

17

tu puoi fare

DELETE FROM `mytable` WHERE `id` > 0

1
L'ho provato, è apparso il seguente errore: Codice di errore: 1142. Il comando DELETE è stato negato all'utente 'root' @ 'localhost' per la tabella 'mytable'
AAEM,

o semplicemente ELIMINA DAmytable
Miloslav Milo Janoušek,

Ciò non ripristinerebbe l'incremento automatico.
vivek_23

13

Come da documentazione mysql , TRUNCATE non può essere utilizzato su tabelle con relazioni di chiave esterna. Non esiste alcuna alternativa completa AFAIK.

L'eliminazione della contraffazione non invoca ancora ON DELETE e ON UPDATE. L'unica soluzione a cui riesco a pensare ATM è di:

  • elimina tutte le righe, rilascia le chiavi esterne, tronca, ricrea le chiavi
  • elimina tutte le righe, ripristina auto_increment (se utilizzato)

Sembrerebbe TRUNCATE in MySQL non è ancora una funzionalità completa (inoltre non invoca trigger). Vedi commento


7
Una nota in merito al fatto che MySQL TRUNCATEè incompleto: troncare non dovrebbe invocare trigger, ecc. Se lo facesse, sarebbe lo stesso DELETE! È indipendente dalla riga, quindi non è in grado di eseguire operazioni relative alla riga (come invocare trigger o esaminare chiavi esterne). Funziona allo stesso modo in Oracle e SQL Server .
Simon MᶜKenzie,

8

Facile se stai usando phpMyAdmin.

Deseleziona l' Enable foreign key checksopzione sotto la SQLscheda ed eseguiTRUNCATE <TABLE_NAME>

inserisci qui la descrizione dell'immagine


8

Mentre questa domanda è stata posta, non lo sapevo, ma ora se usi phpMyAdmin puoi semplicemente aprire il database e selezionare le tabelle che desideri troncare.

  • Nella parte inferiore c'è un menu a discesa con molte opzioni. Aprilo e seleziona l' Emptyopzione sotto l'intestazione Delete data or table.
  • Ti porta automaticamente alla pagina successiva dove c'è un'opzione nella casella chiamata Enable foreign key checks. Deselezionalo e premi il Yespulsante e le tabelle selezionate verranno troncate.

Forse esegue internamente la query suggerita nella risposta di user447951 , ma è molto comodo da usare dall'interfaccia phpMyAdmin.


8

Testato su database MYSQL

Soluzione 1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;

Soluzione 2:

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

Questo funziona per me. Spero che questo ti aiuti anche. Grazie per aver posto questa domanda.


6

La risposta è davvero quella fornita da zerkms , come indicato sull'opzione 1 :

Opzione 1 : che non rischia di danneggiare l'integrità dei dati:

  1. Rimuovi i vincoli
  2. Esegui TRUNCATE
  3. Elimina manualmente le righe che ora hanno riferimenti al nulla
  4. Crea vincoli

La parte difficile è Rimuovere i vincoli , quindi voglio dirti come, nel caso in cui qualcuno debba sapere come farlo:

  1. Esegui la SHOW CREATE TABLE <Table Name>query per vedere qual è il nome del TASTO ESTERO (riquadro rosso nell'immagine sotto):

    inserisci qui la descrizione dell'immagine

  2. Corri ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign Key Name>. Ciò rimuoverà il vincolo di chiave esterna.

  3. Rilascia l' indice associato (attraverso la pagina della struttura della tabella) e il gioco è fatto.

per ricreare chiavi esterne:

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

3

Usa CASCADE

TRUNCATE "products" RESTART IDENTITY CASCADE;

Ma sii pronto per le eliminazioni in cascata)


3
L'OP ha taggato MySQL. Sebbene ciò sia valido in Postgres, non è corretto in MySQL.
Peter,

1

Se il motore di database per le tabelle differisce, otterrai questo errore, quindi cambiali in InnoDB

ALTER TABLE my_table ENGINE = InnoDB;

0

Ottenere il vecchio stato di controllo della chiave esterna e la modalità sql sono il modo migliore per troncare / eliminare la tabella come fa Mysql Workbench durante la sincronizzazione del modello con il database.

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.