ChatGPT解决这个技术问题 Extra ChatGPT

How to truncate a foreign key constrained table?

Why doesn't a TRUNCATE on mygroup work? Even though I have ON DELETE CASCADE SET I get:

ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint (mytest.instance, CONSTRAINT instance_ibfk_1 FOREIGN 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;

I
Insane Skull

Yes you can:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

With these statements, you risk letting in rows into your tables that do not adhere to the FOREIGN KEY constraints.


do we have to set SET FOREIGN_KEY_CHECKS=1; again afterwards?
No, you don't. The setting is only valid during the connection. As soon as you disconnect, the next connection will have it set back to 1.
This does not apply the 'ON DELETE' event in the referenced table, so this is not a complete answer.
If using in PHPMYADMIN, this works only if you use all the transactions in the same SQL window (separated by a ;). This is because each fresh web SQL call will reset the FOREIGN_KEY_CHECKS to 1.
Here is a very good way to find orphaned foreign keys (restore data integrity) in case you are interested http://stackoverflow.com/a/12085689/997776
d
duan

You cannot TRUNCATE a table that has FK constraints applied on it (TRUNCATE is not the same as DELETE).

To work around this, use either of these solutions. Both present risks of damaging the data integrity.

Option 1:

Remove constraints Perform TRUNCATE Delete manually the rows that now have references to nowhere Create constraints

Option 2: suggested by user447951 in their answer

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

@barjonah: actually, it might break data integrity (see stackoverflow.com/questions/5452760/…). So, what you call "light" in the real world is considered to be a bad practice. PS: thanks for the downvote
Here is a very good way to find orphaned foreign keys (restore data integrity) http://stackoverflow.com/a/12085689/997776
@Dung disabling foreign key checks is only allowed in the development period. It breaks any existing relationships. zerkms is 100% right about data integrity. You can not disable foreign key checks on a working database unless you're planning to empty it completely (or at least all related tables)
@Kamlesh it's not my solution, I adviced to not do it that barbaric way.
@zerkms - apologies if I was nto clear, of course the MySQL implementation of truncate and delete are different. What I am saying is truncate implementation could be better - not make it same as delete statement. If the truncate operation does not violate FK constraints (i.e. the child tables are empty), there is no reason to error it saying FK violation - as there would not be any! This is how other RDBMS truncate implementation work.
I
Insane Skull

I would simply do it with :

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

Smart. When you want to delete all records anyway, you might as well reset the auto increment.
This is obviously the best way to do it. No risk of losing constraints, just plain delete. It's worth noticing that DELETE performs slower than TRUNCATE. But since this action is usually performed only rarely, this does not matter.
This is good if that's all you want to do, but DELETE can be absolutely brutal if you have too many rows - since it hits the logs, whereas TRUNCATE just rips the data out. Really depends on use case.
when I'm using delete statement, it report error 1175: You are using safe update mode, just add SET SQL_SAFE_UPDATES = 0; then it's fine
When using this solution, it reports error 1175: You are using safe update mode,... change delete clause to DELETE FROM mydb.mytable where id != 0 makes it perfect.
A
Ajmal Salim

Easy if you are using phpMyAdmin.

Just uncheck Enable foreign key checks option under SQL tab and run TRUNCATE <TABLE_NAME>

https://i.stack.imgur.com/eKvIg.jpg


A
Ali Sadran

you can do

DELETE FROM `mytable` WHERE `id` > 0

I tried it bur, the following error appeared:Error Code: 1142. DELETE command denied to user 'root'@'localhost' for table 'mytable'
or just DELETE FROM mytable
This wouldn't reset the auto increment.
you can most certainly do this. However if you have a table with seven million records, go take a lunch while you're waiting.
@AAEM Could be a few problems. Usually means you need to grant delete permissions to your "root" user on your database, or run flush privileges. See here: stackoverflow.com/questions/4767055/…
K
Kamlesh

Tested on MYSQL Database

Solution 1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;

Solution 2:

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

This works for me. I hope, this will help you also. Thanks for asking this question.


Solution 2 worked for me in phpMyAdmin, but without TRUNCATE table1;
Solutions depend on mysql version that's why I posted 2 solutions. Happy to share and help :)
@Novasol Yes, you are right, it works but if you run TRUNCATE table1; command then mysql table index will be set to 0 internally automatically which will take less time when you make join this table1 with any other table/tables.
O
Omer Sabic

As per mysql documentation, TRUNCATE cannot be used on tables with foreign key relationships. There is no complete alternative AFAIK.

Dropping the contraint still does not invoke the ON DELETE and ON UPDATE. The only solution I can ATM think of is to either:

delete all rows, drop the foreign keys, truncate, recreate keys

delete all rows, reset auto_increment (if used)

It would seem TRUNCATE in MySQL is not a complete feature yet (it also does not invoke triggers). See comment


A note on your point about MySQL's TRUNCATE being incomplete - truncate isn't supposed to invoke triggers etc. If it did, it would just be the same as DELETE! It's row-agnostic, hence it's unable to perform row-related operations (like invoking triggers or examining foreign keys). It works in the same way in Oracle and Sql Server.
Why nobody mentions that TRUNCATE will reset the PRIMARY KEY? With DELETE it won't reset the PRIMARY KEY so your first record will have ID like 325579 which is strange. TRUNCATE shouldn't fail this way IMHO. Truncate is reset the table so it should reset no matter what.
u
user4157124

While this question was asked I didn't know about it, but now if you use phpMyAdmin you can simply open the database and select the table(s) you want to truncate.

At the bottom there is a drop down with many options. Open it and select Empty option under the heading Delete data or table.

It takes you to the next page automatically where there is an option in checkbox called Enable foreign key checks. Just unselect it and press the Yes button and the selected table(s) will be truncated.

Maybe it internally runs the query suggested in user447951's answer, but it is very convenient to use from phpMyAdmin interface.


P
Pmpr.ir

Answer is indeed the one provided by zerkms, as stated on Option 1:

Option 1: which does not risk damage to data integrity: Remove constraints Perform TRUNCATE Delete manually the rows that now have references to nowhere Create constraints

The tricky part is Removing constraints, so I want to tell you how, in case someone needs to know how to do that:

Run SHOW CREATE TABLE

query to see what is your FOREIGN KEY's name (Red frame in below image): Run ALTER TABLE
DROP FOREIGN KEY . This will remove the foreign key constraint. Drop the associated Index (through table structure page), and you are done.

to re-create foreign keys:

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

P
P.Githinji

How to truncate a foreign key constrained table? This illustration will demonstrate how to solve mysql error when truncating a table with foreign key constraint. If you are using PHPMYADMIN, it is very easy to truncate a table with foreign key constraint.

Login to PHPMYADMIN and click the table you want to truncate. Then go to SQL tab Place your code to truncate the table in the SQL Editor example truncate table students; Replace students with the name of the table. At the bottom of the editor untick the "Enable foreign key checks" checkbox as shown below:

https://i.stack.imgur.com/IMPNW.png

It will work like magic.


A
Alexus1024

Just use CASCADE

TRUNCATE "products" RESTART IDENTITY CASCADE;

But be ready for cascade deletes )


The OP tagged MySQL. While this is valid in Postgres, it is incorrect in MySQL.
m
mwafi

Another workaround is delete all rows in the table then reset auto-increment columns:

delete from table_name where 1

then Run:

ALTER TABLE table_name AUTO_INCREMENT = 1

V
Vijay Arun

Getting the old foreign key check state and sql mode are best way to truncate / Drop the table as Mysql Workbench do while synchronizing model to 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;

s
sajad abbasi

If the database engine for tables differ you will get this error so change them to InnoDB

ALTER TABLE my_table ENGINE = InnoDB;

H
HadiNiazi

if you are using laravel migrations, you can do this using facades helpers

prefer to use Eloquent objects, answer the "Eloquent" way

 Schema::disableForeignKeyConstraints();
 Teacher::truncate();
 Schema::enableForeignKeyConstraints();

In Laravel 7 and 8, for compatibility across 4 databases (MySql, Postgres, SQLite and SqlServer) and no Eloquent, you can use:

Schema::disableForeignKeyConstraints();
    DB::table('teachers')->truncate();
Schema::enableForeignKeyConstraints();