【问题标题】:SQL delete all rows for all childrenSQL 删除所有子项的所有行
【发布时间】:2014-05-30 04:02:38
【问题描述】:

在 MySQL 中是否可以根据父表递归删除所有子表?

假设我有

+-------+
|TBL1.id|  
+-------+  

+-------+--------------------------+  
|TBL2.id|TBL2.parentId (FK TBL1.id)|  
+-------+--------------------------+  

+-------+--------------------------+
|TBL3.id|TBL3.parentId (FK TBL2.id)|  
+-------+--------------------------+  

现在,我不能从 TBL1 中删除所有行,因为 TBL2 引用了 TBL1.id,我不能删除 TBL2,因为 TLB3 引用了 TBL2。

是否可以使用 MySQL 生成一个 SQL 查询来列出必须删除的表的顺序?还是列出表的依赖关系,从最远的孩子开始?

我不想删除表,只是删除一组表的所有行及其子项,以及它们的子项,...

目前我有几个脚本,每个父表一个用于删除所有子表,但我想自动执行。

编辑 1: 数据库处于开发模式,因此仍在向其中添加新表和约束。

我不拥有没有级联删除的数据库。我可以将级联删除添加到发送给我的副本中,但这与使用我今天拥有的脚本一样多。

【问题讨论】:

  • 您是否尝试修改 FK 定义以使用 ON DELETE CASCADE?还是我理解错了,不能满足你的需要?
  • 在帖子中添加了更多详细信息。不幸的是,级联删除不是一种选择。
  • 您要delete 行还是drop 表?
  • 我想删除行。

标签: mysql


【解决方案1】:

假设您要删除 TBL1 上 ID 等于 5 的所有行,以及表中的所有相关行:TBL2 和 TBL3,您可以像这样在单个事务中执行此操作:

START TRANSACTION
DELETE FROM TBL3 WHERE EXISTS (SELECT 1 FROM TBL2 JOIN TBL1 ON TBL1.id = TBL2. parentId AND TBL1.id = 5 WHERE id = TBL3.parentId);
DELETE FROM TBL2 WHERE EXISTS (SELECT 1 FROM TBL1 WHERE id = TBL2.parentId AND id = 5);
DELETE FROM TBL1 WHERE id = 5;
COMMIT

如果您在表上遵循约定命名字段,则可以使用 PLSQL 查询 INFORMATION_SCHEMA.TABLES 视图动态生成脚本:

SELECT table_name, column_name FROM INFORMATION_SCHEMA.TABLES t
   JOIN INFORMATION_SCHEMA.COLUMNS c ON c.table_name = t.table_name AND table_schema = 'db_name' 
  WHERE table_schema = 'db_name'
  AND table_name LIKE 'TBL_' AND column_name LIKE 'parentId'
  ORDER BY table_name DESC

【讨论】:

  • 这就是我的脚本所做的。但是如果一个新的 TBL4 现在依赖于 TBL1、TBL2 或 TBL3,它就会失败。我正在寻找一个通用的解决方案。也许读字典?
  • 可以动态生成脚本,但必须遵循命名字段的约定...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2014-07-02
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 2016-09-08
相关资源
最近更新 更多