主外键表关联数据的同时删除
2016-07-26 19:26
417 查看
主外键表关联数据的同时删除 2008-07-31 18:28:00
标签:主外键表
关联数据
删除
休闲
职场
原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本声明。否则将追究法律责任。http://zhaizhenxing.blog.51cto.com/643480/134530
今天产品有个操作,要求将满足某个条件的主表和相关联的几个子表的数据全部删除,其实这个要求很简单,如果子表在创建外键的时候指定了ON DELETE CASCADE,则直接从主表中删除相关记录,子表中数据也会一起删除。但是现在的子表外键创建时候没有加此语句,看来此方法不通;
接着想到了mysql里面支持一次进行多表删除,即delete a,b from a,b where ...这种语法,尝试如下:
mysql> delete a,b from parent a,child2 b where a.id=b.parent_id and a.id=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test/child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
显然,违反了外键约束而报错,也就是说上述语句是按照先主后从的的顺序进行删除操作,而从表中由于存在相应记录而导致删除失败;那么,如果将表的删除顺序颠倒一下就可以按照先从后主的顺序删除呢?我们测试一下:
mysql> delete a,b from child2 a,parent b where a.parent_id=b.id and b.id=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test/child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
看来还是不行,母子表的关联删除看来和表的连接顺序无关,我们再次验证一下:
mysql> set profiling=1;
Query OK, 0 rows affected (0.03 sec)
mysql> select @@profiling;
+-------------+
| @@profiling |
+-------------+
| 1 |
+-------------+
1 row in set (0.00 sec)
mysql> show profiles;
+----------+------------+--------------------+
| Query_ID | Duration | Query |
+----------+------------+--------------------+
| 1 | 0.00011900 | select @@profiling |
+----------+------------+--------------------+
1 row in set (0.00 sec)
mysql> delete a,b from child2 a,parent b where a.parent_id=b.id and b.id=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test/child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
mysql> show profiles;
+----------+------------+---------------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+---------------------------------------------------------------------+
| 1 | 0.00011900 | select @@profiling |
| 2 | 0.03273800 | delete a,b from child2 a,parent b where a.parent_id=b.id and b.id=2 |
+----------+------------+---------------------------------------------------------------------+
2 rows in set (0.00 sec)
mysql> show profile for query 2;
+--------------------------+----------+
| Status | Duration |
+--------------------------+----------+
| (initialization) | 0.000077 |
| init | 0.000011 |
| Opening tables | 0.000018 |
| System lock | 0.000009 |
| Table lock | 0.00002 |
| init | 0.000027 |
| deleting from main table | 0.000007 |
| optimizing | 0.000016 |
| statistics | 0.000106 |
| preparing | 0.000024 |
| executing | 0.000007 |
| Sending data | 0.000615 |
| end | 0.000017 |
| query end | 0.000008 |
| freeing items | 0.000015 |
| closing tables | 0.031749 |
| logging slow query | 0.000012 |
+--------------------------+----------+
17 rows in set (0.03 sec)
可以看到,执行步骤中有一句“deleting from main table”,也就是从主表删除,而没有删除子表的语句,看来子表的数据按照这种方式是无法删除的。
那么如果指定了on delete cascade,执行步骤又是什么样呢?
mysql> delete parent from parent where id=2;;
Query OK, 1 row affected (0.03 sec)
mysql> show profile for query 14
-> ;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| (initialization) | 0.000062 |
| init | 0.000008 |
| Opening tables | 0.000018 |
| System lock | 0.000008 |
| Table lock | 0.000018 |
| init | 0.000023 |
| deleting from main table | 0.000007 |
| optimizing | 0.000012 |
| statistics | 0.000068 |
| preparing | 0.000015 |
| executing | 0.000007 |
| Sending data | 0.000145 |
| deleting from reference tables | 0.000007 |
| end | 0.02809 |
| query end | 0.000014 |
| freeing items | 0.000016 |
| closing tables | 0.000017 |
| logging slow query | 0.000006 |
+--------------------------------+----------+
18 rows in set (0.00 sec)
这次,多了一步“deleting from reference tables ”,显然主从表都会进行删除操作的。
最后,只能按照最笨的办法,先删除子表,再删除主表:
mysql> delete from child2 where id=3;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from parent where id=3;
Query OK, 1 row affected (0.03 sec)
如果有多层的母子表,则按照从最内层的子表开始,一直到最外层的主表的顺利来完成删除操作,如下:
delete d
from a,b,c,d
where a.id=b.order_id and b.id=c.order_record_id and c.id=d.ORDER_FACTORY_ID
and a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
delete c
from a,b,c
where a.id=b.order_id and b.id=c.order_record_id
and a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
delete b
from a,b
where a.id=b.order_id
and a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
delete a
from order_tab a
where a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
看来设置外键的时候还是应该考虑好on delete 和on udpate的操作action,防止这些无谓的麻烦。
本文出自 “帅小伙的博客” 博客,请务必保留此出处http://zhaizhenxing.blog.51cto.com/643480/134530
标签:主外键表
关联数据
删除
休闲
职场
原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本声明。否则将追究法律责任。http://zhaizhenxing.blog.51cto.com/643480/134530
今天产品有个操作,要求将满足某个条件的主表和相关联的几个子表的数据全部删除,其实这个要求很简单,如果子表在创建外键的时候指定了ON DELETE CASCADE,则直接从主表中删除相关记录,子表中数据也会一起删除。但是现在的子表外键创建时候没有加此语句,看来此方法不通;
接着想到了mysql里面支持一次进行多表删除,即delete a,b from a,b where ...这种语法,尝试如下:
mysql> delete a,b from parent a,child2 b where a.id=b.parent_id and a.id=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test/child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
显然,违反了外键约束而报错,也就是说上述语句是按照先主后从的的顺序进行删除操作,而从表中由于存在相应记录而导致删除失败;那么,如果将表的删除顺序颠倒一下就可以按照先从后主的顺序删除呢?我们测试一下:
mysql> delete a,b from child2 a,parent b where a.parent_id=b.id and b.id=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test/child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
看来还是不行,母子表的关联删除看来和表的连接顺序无关,我们再次验证一下:
mysql> set profiling=1;
Query OK, 0 rows affected (0.03 sec)
mysql> select @@profiling;
+-------------+
| @@profiling |
+-------------+
| 1 |
+-------------+
1 row in set (0.00 sec)
mysql> show profiles;
+----------+------------+--------------------+
| Query_ID | Duration | Query |
+----------+------------+--------------------+
| 1 | 0.00011900 | select @@profiling |
+----------+------------+--------------------+
1 row in set (0.00 sec)
mysql> delete a,b from child2 a,parent b where a.parent_id=b.id and b.id=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test/child2`, CONSTRAINT `child2_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
mysql> show profiles;
+----------+------------+---------------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+---------------------------------------------------------------------+
| 1 | 0.00011900 | select @@profiling |
| 2 | 0.03273800 | delete a,b from child2 a,parent b where a.parent_id=b.id and b.id=2 |
+----------+------------+---------------------------------------------------------------------+
2 rows in set (0.00 sec)
mysql> show profile for query 2;
+--------------------------+----------+
| Status | Duration |
+--------------------------+----------+
| (initialization) | 0.000077 |
| init | 0.000011 |
| Opening tables | 0.000018 |
| System lock | 0.000009 |
| Table lock | 0.00002 |
| init | 0.000027 |
| deleting from main table | 0.000007 |
| optimizing | 0.000016 |
| statistics | 0.000106 |
| preparing | 0.000024 |
| executing | 0.000007 |
| Sending data | 0.000615 |
| end | 0.000017 |
| query end | 0.000008 |
| freeing items | 0.000015 |
| closing tables | 0.031749 |
| logging slow query | 0.000012 |
+--------------------------+----------+
17 rows in set (0.03 sec)
可以看到,执行步骤中有一句“deleting from main table”,也就是从主表删除,而没有删除子表的语句,看来子表的数据按照这种方式是无法删除的。
那么如果指定了on delete cascade,执行步骤又是什么样呢?
mysql> delete parent from parent where id=2;;
Query OK, 1 row affected (0.03 sec)
mysql> show profile for query 14
-> ;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| (initialization) | 0.000062 |
| init | 0.000008 |
| Opening tables | 0.000018 |
| System lock | 0.000008 |
| Table lock | 0.000018 |
| init | 0.000023 |
| deleting from main table | 0.000007 |
| optimizing | 0.000012 |
| statistics | 0.000068 |
| preparing | 0.000015 |
| executing | 0.000007 |
| Sending data | 0.000145 |
| deleting from reference tables | 0.000007 |
| end | 0.02809 |
| query end | 0.000014 |
| freeing items | 0.000016 |
| closing tables | 0.000017 |
| logging slow query | 0.000006 |
+--------------------------------+----------+
18 rows in set (0.00 sec)
这次,多了一步“deleting from reference tables ”,显然主从表都会进行删除操作的。
最后,只能按照最笨的办法,先删除子表,再删除主表:
mysql> delete from child2 where id=3;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from parent where id=3;
Query OK, 1 row affected (0.03 sec)
如果有多层的母子表,则按照从最内层的子表开始,一直到最外层的主表的顺利来完成删除操作,如下:
delete d
from a,b,c,d
where a.id=b.order_id and b.id=c.order_record_id and c.id=d.ORDER_FACTORY_ID
and a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
delete c
from a,b,c
where a.id=b.order_id and b.id=c.order_record_id
and a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
delete b
from a,b
where a.id=b.order_id
and a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
delete a
from order_tab a
where a.old_id>=20171059 and (a.card_type_id=21 or a.card_type_id=22) and a.guangzhou_order_id is not null;
看来设置外键的时候还是应该考虑好on delete 和on udpate的操作action,防止这些无谓的麻烦。
本文出自 “帅小伙的博客” 博客,请务必保留此出处http://zhaizhenxing.blog.51cto.com/643480/134530
相关文章推荐
- 编译boost库 I
- Java工具箱之字符编码工具类
- linux环境下同时使用静态库、动态库编译程序
- No.009 Palindrome Number
- CentOS从入门到精通系列之PPTP
- Material Design的使用
- Web网站发布权限问题
- Linux 下的Tmux的使用记录
- React-Native for iOS
- Dynamics CRM 2016 安装
- POJ 1905 Expanding Rods(二分)
- object类中相关方法
- 一个小白的内心自白
- HDU4907Task schedule二分
- 汉诺塔(一)
- Class.getResource和ClassLoader.getResource的路径区别
- interface 接口的特点
- 补充——理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- cocos2dx-lua ios系统访问系统相册
- 【深入理解JVM】内存模型