跳至主要内容

删除带外键的表【foreign key constraint fails】报错

遥想当时正在学hibernate的时候,刚好学到了一对多,多对多的关联操作。时间也正是刚好在那是有了一个项目,把各表的间的结构还理清,俗话说学到就要用到,就把这些表的结构都能配置级联关系的都把它配上。没想到就在这里给自己放了个小坑。前几天在一个帖子中看到别人说,尽量少配些ORM约束,数据库的外键约束什么的。当时还不以为然。没想到我就遇到了这个问题,或许对数据库操还是不是很熟悉的人约束真的不要配太多。不过有自然有其的好处就是。
今天在删除一张表的数据的时候报了如下错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
09:55:49.144 [http-nio-8080-exec-6] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Cannot delete or update a parent row: a foreign key constraint fails (`checkin`.`right_umenu`, CONSTRAINT `FKnmg8itd642tdyn6qh1q42h60r` FOREIGN KEY (`menu_detailPid`) REFERENCES `menu_detail` (`id`))
09:55:49.151 [http-nio-8080-exec-6] ERROR org.hibernate.internal.SessionImpl - HHH000346: Error during managed flush [could not execute statement]


org.hibernate.exception.ConstraintViolationException: could not execute statement
 at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
 at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
 at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
 at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
 at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207)
 at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45)
 at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3198)
 .......

​ 在网上查找后得到的结果和我认为的是一样的,就是外键的问题引发的(当然报错里信息都写了foreign key什么的还不知道,那怎么行(●ˇ∀ˇ●))。网上是说:表之间强制生成了外键,在删除操作时,数据库会检查表间的关系导致无法删除。
解决办法

1
2
3
4
5
SET foreign_key_checks = 0;  // 先设置外键约束检查关闭
 
drop table table1;  // 删除表,如果要删除视图,也是如此
 
SET foreign_key_checks = 1; // 开启外键约束检查,以保持表结构完整性

原理:
MySQL的环境变量中存在一个foreign_key_checks,这是默认检查外键的配置项,如果将其设置为0,则表示不检查外键约束。查看foreign_key_checks的值:

1
show VARIABLES like "foreign%";

然而,然而。我即使把外键约束检查关闭,但是在打开检查的地方又还会报错。这我就无奈了。
不过我在尝试时把,外键的删除项由 RESTRICT 改为 CASCADE 时不但能删除且不影响我的另一个方法的执行,而且的更方便的执行了我想写的方法。
后面又继续查,这是数据库定义外键的一个选项,操作时可以知道update 和delete 后面可以跟的词语有四个 :
no action , set null , set default ,cascade 。

1
2
3
4
5
6
7
no action 表示 不做任何操作,

set null 表示在外键表中将相应字段设置为null

set default 表示设置为默认值(restrict)

cascade 表示级联操作,就是说,如果主键表中被参考字段更新,外键表中也更新,主键表中的记录被删除,外键表中改行也相应删除

所以当我如此设置的时候就把想做的级联删除也都执行了,数据库的很多东西都还要去补啊。

评论

此博客中的热门博文

【图集】言叶之庭(言の葉の庭)

隐约雷鸣 阴霾天空 但盼风雨来 能留你在此 隐约雷鸣 阴霾天空 即使天无雨 我亦留此地 ——万叶集 《言叶之庭》

关于Apache本地能访问外网不能访问的问题

在配置apache和tomcat时,把它们都配置好,放到服务器中发现外网不能访问 解决: I,可能是防火墙限制了。 1,首先启动Apache,在本地打开浏览器访问指定路径成功。 2,在系统的控制面板里打开防火墙设置,进入高级设置。 3,在高级设置里右键点击“入站规则”,选择“新建规则”。 4,在规则导向里,类型选“端口”,协议选“TCP”。 5,指定本地端口号“80”。(此处的80与Apache配置里指定的端口号要一致) 6,下一步的“操作”选择“允许连接”即可。 7,“配置文件”选择“域、专用、公用”即可。 8,“名称”和“描述”自定义,能识别即可。最后保存退出。 9, 无需重启apache II,也可能是配置出了问题 可能是配置中没有允许外部访问,则Apache服务器是2.4.0以上 版本,将虚拟主机的进行如下配置: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 < VirtualHost * :80 > < Directory " C: / www "> Options FollowSymLinks AllowOverride All Order allow,deny Allow from all Require all granted </ Directory > ServerAdmin xdfsfsffs@xd.com DocumentRoot "C:/www" ServerName www.test.com ServerAlias test.com ErrorLog "logs/test.bin-error_log" CustomLog "logs/test.bin-access_log" common </ VirtualHost >