如何截断外键约束表?

use*_*986 601 mysql truncate constraints foreign-keys dml

为什么没有一个TRUNCATEmygroup工作?即使ON DELETE CASCADE SET我得到了:

错误1701(42000):无法截断外键约束中引用的表(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;
Run Code Online (Sandbox Code Playgroud)

use*_*951 1265

是的你可以:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;
Run Code Online (Sandbox Code Playgroud)

使用这些语句,您可能会冒险将行放入不符合FOREIGN KEY约束的表中.

  • 不,你没有.该设置仅在连接期间有效.断开连接后,下一次连接会将其设置为1. (73认同)
  • 我们必须设置SET FOREIGN_KEY_CHECKS = 1; 之后又一次? (29认同)
  • 这不会在引用的表中应用"ON DELETE"事件,因此这不是一个完整的答案. (7认同)
  • 如果在PHPMYADMIN中使用,仅当您在同一SQL窗口中使用所有事务(由`;`分隔)时,此方法才有效.这是因为每次新的Web SQL调用都会将`FOREIGN_KEY_CHECKS`重置为1. (5认同)

zer*_*kms 911

您不能TRUNCATE在其上应用FK约束的表(TRUNCATE与其不同DELETE).

要解决此问题,请使用以下任一解决方案.两者都存在损害数据完整性的风险.

选项1:

  1. 删除约束
  2. 演出 TRUNCATE
  3. 手动删除现在引用无处的行
  4. 创建约束

选项2:用户 447951答案中建议

SET FOREIGN_KEY_CHECKS = 0; 
TRUNCATE table $table_name; 
SET FOREIGN_KEY_CHECKS = 1;
Run Code Online (Sandbox Code Playgroud)

  • @barjonah:实际上,它可能会破坏数据完整性(请参阅http://stackoverflow.com/questions/5452760/truncate-foreign-key-constrained-table/5452798#comment17490806_8074510).所以,你在现实世界中称之为"光明"的东西被认为是一种不好的做法.PS:谢谢你的downvote (43认同)
  • 这里有一个很好的方法可以找到孤立的外键(恢复数据完整性)[http://stackoverflow.com/a/12085689/997776](http://stackoverflow.com/a/12085689/997776) (2认同)
  • @Dung禁用外键检查仅在开发期间允许.它打破了任何现有的关系.zerkms对数据完整性100%正确.您无法在工作数据库上禁用外键检查,除非您计划完全清空它(或至少所有相关表) (2认同)
  • @Kamlesh,这不是我的解决方案,我建议不要这样做野蛮的方式。 (2认同)

Geo*_*ili 156

我只想这样做:

DELETE FROM mytest.instance;
ALTER TABLE mytest.instance AUTO_INCREMENT = 1;
Run Code Online (Sandbox Code Playgroud)

  • 聪明.当您想要删除所有记录时,您也可以重置自动增量. (5认同)
  • 这显然是最好的方法.没有丢失约束的风险,只是简单的删除.值得注意的是,"DELETE"的执行速度比"TRUNCATE"慢.但由于此动作通常很少执行,因此无关紧要. (5认同)
  • 如果这就是您想要做的一切,那么这很好,但是如果您有太多行,“DELETE”可能绝对是残酷的 - 因为它会命中日志,而“TRUNCATE”只会删除数据。确实取决于用例。 (3认同)
  • 使用此解决方案时,会报告“错误 1175:您正在使用安全更新模式,...”将删除子句更改为“DELETE FROM mydb.mytable where id != 0”使其完美。 (3认同)
  • 当我使用delete语句时,它报告错误1175:您正在使用安全更新模式,只需添加SET SQL_SAFE_UPDATES = 0; 那么就可以了 (2认同)

小智 17

你可以做

DELETE FROM `mytable` WHERE `id` > 0
Run Code Online (Sandbox Code Playgroud)

  • 或者只是从 `mytable` 中删除 (3认同)
  • 这不会重置自动增量。 (3认同)
  • 你绝对可以做到这一点。但是,如果您的桌子上有 700 万条记录,那么您可以在等待时吃顿午餐。 (2认同)

Ome*_*bic 12

根据mysql文档,TRUNCATE不能用于具有外键关系的表.没有完整的替代AFAIK.

删除约束仍然不会调用ON DELETE和ON UPDATE.我能想到的唯一解决方案是:

  • 删除所有行,删除外键,截断,重新创建键
  • 删除所有行,重置auto_increment(如果使用)

在MySQL中似乎TRUNCATE还不是一个完整的功能(它也不会调用触发器). 见评论

  • 关于你关于MySQL的`TRUNCATE`是不完整的观点的一个注释 - truncate不应该调用触发器等.如果确实如此,它将与`DELETE`相同!它与行无关,因此无法执行与行相关的操作(如调用触发器或检查外键).它在[Oracle](http://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_10007.htm#SQLRF01707)和[Sql Server](https://msdn.microsoft)中的工作方式相同. .COM/EN-US /库/ ms177570.aspx). (7认同)

Kam*_*esh 10

在 MYSQL 数据库上测试

解决方案1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;
Run Code Online (Sandbox Code Playgroud)

解决方案2:

DELETE FROM table1;
ALTER TABLE table1 AUTO_INCREMENT = 1;
TRUNCATE table1;
Run Code Online (Sandbox Code Playgroud)

这对我有用。我希望,这也能帮助你。感谢您提出这个问题。


Rol*_*Koh 8

虽然这个问题是在5年前提出的,但我不知道当时MySql中存在这个功能,但现在如果你使用phpmyadmin,你只需打开数据库,然后选择你要截断的表.在底部有一个下拉列表,其中列出了许多选项.打开它并选择标题删除数据或表格下的清空选项.它会自动转到下一页,其中复选框中有一个选项,称为启用外键检查.只需取消选择它并按是按钮,所选表格将被截断.可以在内部运行user447951的答案中建议的查询.但是从phpmyadmin界面使用非常方便.


Ajm*_*lim 7

如果您使用的是phpMyAdmin,则很容易。

只需取消选中Enable foreign key checks选项SQL卡下的选项并运行TRUNCATE <TABLE_NAME>

在此处输入图片说明


Pmp*_*mpr 6

答案确实zerkms提供的答案,如选项1所述

选项1:不会冒损坏数据完整性的风险:

  1. 消除约束
  2. 执行截断
  3. 手动删除现在无处引用的行
  4. 创建约束

棘手的部分是删除约束,所以我想告诉您如何操作,以防有人需要知道如何做:

  1. 运行SHOW CREATE TABLE <Table Name>查询以查看您的FOREIGN KEY的名称是什么(下图中的红色框):

    在此处输入图片说明

  2. 运行ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign Key Name>。这将删除外键约束。

  3. 删除关联的索引(通过表结构页面),就可以完成。

重新创建外键:

ALTER TABLE <Table Name>
ADD FOREIGN KEY (<Field Name>) REFERENCES <Foreign Table Name>(<Field Name>);
Run Code Online (Sandbox Code Playgroud)