ChatGPT解决这个技术问题 Extra ChatGPT

如何截断外键约束表?

为什么 mygroup 上的 TRUNCATE 不起作用?即使我有 ON DELETE CASCADE SET 我得到:

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

是的你可以:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

使用这些语句,您可能会将不遵守 FOREIGN KEY 约束的行放入表中。


我们是否必须设置 SET FOREIGN_KEY_CHECKS=1;之后再次?
不,你没有。该设置仅在连接期间有效。断开连接后,下一个连接会将其设置回 1。
这不适用于引用表中的“ON DELETE”事件,因此这不是一个完整的答案。
如果在 PHPMYADMIN 中使用,这仅在您使用同一 SQL 窗口中的所有事务时才有效(由 ; 分隔)。这是因为每个新的 Web SQL 调用都会将 FOREIGN_KEY_CHECKS 重置为 1。
如果您有兴趣,这是查找孤立外键(恢复数据完整性)的好方法http://stackoverflow.com/a/12085689/997776
d
duan

您不能TRUNCATE 应用了 FK 约束的表(TRUNCATEDELETE 不同)。

要解决此问题,请使用这些解决方案之一。两者都存在破坏数据完整性的风险。

选项1:

删除约束 执行 TRUNCATE 手动删除现在无处引用的行 创建约束

选项 2: user447951their answer 中建议

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

@barjonah:实际上,它可能会破坏数据完整性(请参阅 stackoverflow.com/questions/5452760/…)。所以,你在现实世界中所谓的“光”被认为是一种不好的做法。 PS:感谢投反对票
这是查找孤立外键(恢复数据完整性)的一种非常好的方法http://stackoverflow.com/a/12085689/997776
@Dung 仅在开发期间允许禁用外键检查。它打破了任何现有的关系。 zerkms 在数据完整性方面是 100% 正确的。除非您打算完全清空它(或至少清空所有相关表),否则您不能在工作数据库上禁用外键检查
@Kamlesh 这不是我的解决方案,我建议不要以那种野蛮的方式去做。
@zerkms - 抱歉,如果我不清楚,当然 MySQL 的 truncate 和 delete 实现是不同的。我要说的是 truncate 实现可能会更好 - 不要让它与 delete 语句相同。如果截断操作没有违反 FK 约束(即子表为空),则没有理由错误地说它违反 FK - 因为不会有任何错误!这就是其他 RDBMS 截断实现的工作方式。
I
Insane Skull

我会简单地这样做:

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

聪明的。当您无论如何都想删除所有记录时,您不妨重置自动增量。
这显然是最好的方法。没有失去约束的风险,只是简单的删除。值得注意的是,DELETE 的执行速度比 TRUNCATE 慢。但是由于这个动作通常很少执行,所以这无关紧要。
如果您只想这样做,这很好,但如果您有太多行,DELETE 可能绝对是残酷的 - 因为它会命中日志,而 TRUNCATE 只是将数据撕掉。真的取决于用例。
当我使用delete语句时,报错1175: You are using safe update mode, just add SET SQL_SAFE_UPDATES = 0;然后就好了
使用此解决方案时,它报告 error 1175: You are using safe update mode,... 将删除子句更改为 DELETE FROM mydb.mytable where id != 0 使其完美。
A
Ajmal Salim

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

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

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


A
Ali Sadran

你可以做

DELETE FROM `mytable` WHERE `id` > 0

我试了一下bur,出现如下错误:Error Code: 1142. DELETE command denied to user 'root'@'localhost' for table 'mytable'
或者只是从 mytable 中删除
这不会重置自动增量。
你当然可以做到这一点。但是,如果您有一张包含 700 万条记录的表,请在等待时去吃午饭。
@AAEM 可能是一些问题。通常意味着您需要向数据库上的“root”用户授予删除权限,或者运行 flush privileges。见这里:stackoverflow.com/questions/4767055/…
K
Kamlesh

在 MYSQL 数据库上测试

解决方案1:

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE table1;

解决方案2:

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

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


解决方案 2 在 phpMyAdmin 中为我工作,但没有 TRUNCATE table1;
解决方案取决于 mysql 版本,这就是我发布 2 个解决方案的原因。乐于分享和帮助:)
@Novasol 是的,你是对的,它可以工作,但如果你运行 TRUNCATE table1;命令然后mysql表索引将在内部自动设置为0,当您将此表1与任何其他表/表连接时,这将花费更少的时间。
O
Omer Sabic

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

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

删除所有行,删除外键,截断,重新创建键

删除所有行,重置 auto_increment(如果使用)

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


关于您关于 MySQL 的 TRUNCATE 不完整的观点的注释 - 截断不应该调用触发器等。如果确实如此,它将与 DELETE 相同!它与行无关,因此无法执行与行相关的操作(如调用触发器或检查外键)。它在 OracleSql Server 中的工作方式相同。
为什么没有人提到 TRUNCATE 会重置 PRIMARY KEY?使用 DELETE 它不会重置 PRIMARY KEY,因此您的第一条记录将具有像 325579 这样的 ID,这很奇怪。 TRUNCATE 不应该以这种方式失败恕我直言。截断是重置表,所以无论如何它都应该重置。
u
user4157124

虽然有人问了这个问题,但我不知道,但现在如果您使用 phpMyAdmin,您只需打开数据库并选择要截断的表即可。

在底部有一个包含许多选项的下拉菜单。打开它并在标题删除数据或表下选择空选项。

它会自动将您带到下一页,其中复选框中有一个名为“启用外键检查”的选项。只需取消选择它并按是按钮,所选表将被截断。

也许它在内部运行 user447951's answer 中建议的查询,但从 phpMyAdmin 界面使用非常方便。


P
Pmpr.ir

答案确实是 the one provided by zerkms,如 选项 1 所述:

选项 1:不会有损害数据完整性的风险:删除约束执行 TRUNCATE 手动删除现在对无处引用的行 创建约束

棘手的部分是消除约束,所以我想告诉你如何,以防有人需要知道如何做到这一点:

运行 SHOW CREATE TABLE

查询以查看您的 FOREIGN KEY 的名称(下图中的红框):运行 ALTER TABLE
DROP FOREIGN KEY 。这将删除外键约束。删除关联的索引(通过表结构页面),您就完成了。

重新创建外键:

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

P
P.Githinji

如何截断外键约束表?此图将演示如何在截断具有外键约束的表时解决 mysql 错误。如果您使用 PHPMYADMIN,很容易截断带有外键约束的表。

登录到 PHPMYADMIN 并单击要截断的表。然后转到 SQL 选项卡将您的代码截断表放在 SQL 编辑器示例中截断表学生;用表的名称替换学生。在编辑器底部取消勾选“启用外键检查”复选框,如下所示:

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

它会像魔术一样工作。


A
Alexus1024

只需使用 CASCADE

TRUNCATE "products" RESTART IDENTITY CASCADE;

但准备好级联删除)


OP 标记了 MySQL。虽然这在 Postgres 中有效,但在 MySQL 中是不正确的。
m
mwafi

另一种解决方法是删除表中的所有行,然后重置自动增量列:

delete from table_name where 1

然后运行:

ALTER TABLE table_name AUTO_INCREMENT = 1

V
Vijay Arun

获取旧的外键检查状态和 sql 模式是在将模型同步到数据库时像 Mysql Workbench 那样截断/删除表的最佳方法。

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

如果表的数据库引擎不同,您将收到此错误,因此请将它们更改为 InnoDB

ALTER TABLE my_table ENGINE = InnoDB;

H
HadiNiazi

如果你正在使用 laravel 迁移,你可以使用 Facades 助手来做到这一点

更喜欢使用 Eloquent 对象,回答“Eloquent”方式

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

在 Laravel 7 和 8 中,为了兼容 4 个数据库(MySql、Postgres、SQLite 和 SqlServer)并且没有 Eloquent,您可以使用:

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