title: 刪除帶外鍵的表【foreign key constraint fails】報錯
date: 2018-08-02 21:59:06
tags: 數據庫
遙想當時正在學hibernate的時候,剛好學到了一對多,多對多的關聯操作。時間也正是剛好在那是有了一個項目,把各表的間的結構還理清,俗話說學到就要用到,就把這些表的結構都能配置級聯關系的都把它配上。沒想到就在這里給自己放了個小坑。前幾天在一個帖子中看到別人說,盡量少配些ORM約束,數據庫的外鍵約束什么的。當時還不以為然。沒想到我就遇到了這個問題,或許對數據庫操還是不是很熟悉的人約束真的不要配太多。不過有自然有其的好處就是。
今天在刪除一張表的數據的時候報了如下錯誤:
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什么的還不知道,那怎么行(●ˇ∀ˇ●))。網上是說:表之間強制生成了外鍵,在刪除操作時,數據庫會檢查表間的關系導致無法刪除。
解決辦法:
SET foreign_key_checks = 0; // 先設置外鍵約束檢查關閉
drop table table1; // 刪除表,如果要刪除視圖,也是如此
SET foreign_key_checks = 1; // 開啟外鍵約束檢查,以保持表結構完整性
原理:
MySQL的環境變量中存在一個foreign_key_checks,這是默認檢查外鍵的配置項,如果將其設置為0,則表示不檢查外鍵約束。查看foreign_key_checks的值:
show VARIABLES like "foreign%";
然而,然而。我即使把外鍵約束檢查關閉,但是在打開檢查的地方又還會報錯。這我就無奈了。
不過我在嘗試時把,外鍵的刪除項由 RESTRICT 改為 CASCADE 時不但能刪除且不影響我的另一個方法的執行,而且的更方便的執行了我想寫的方法。
后面又繼續查,這是數據庫定義外鍵的一個選項,操作時可以知道update 和delete 后面可以跟的詞語有四個 :
no action , set null , set default ,cascade 。
no action 表示 不做任何操作,
set null 表示在外鍵表中將相應字段設置為null
set default 表示設置為默認值(restrict)
cascade 表示級聯操作,就是說,如果主鍵表中被參考字段更新,外鍵表中也更新,主鍵表中的記錄被刪除,外鍵表中改行也相應刪除
所以當我如此設置的時候就把想做的級聯刪除也都執行了,數據庫的很多東西都還要去補啊。