MySQL DELETE 오류(외래 키 제약 조건 실패)

프로젝트 진행 중 MyBatis를 이용하여 DB에 저장된 데이터 삭제 기능을 구현해야 했습니다.


위의 ERD에서 이력서 테이블에 저장된 특정 행을 삭제하려고 했습니다.

1. 문제

<delete id="deleteResume">
    delete from resumelist where res_num = #{res_num}
</delete>

위의 쿼리를 작성하고 실행하십시오.

이유: java.sql.SQLIntegrityConstraintViolationException: 부모 행을 삭제하거나 업데이트할 수 없습니다. 외래 키 제약 조건이 실패했습니다. 참조 무결성에 대한 FK 제약위반이 감지되었습니다

CV 테이블의 PK 값인 res_num이 Education, Certification 및 Career 테이블에서 참조되었기 때문에 삭제할 수 없습니다.

2코스

1) 첫 시도

위의 오류를 수정하려고 시도한 첫 번째 방법은 교육, 자격 및 경력 테이블에서 참조되는 FK에 ON DELETE CASCADE 옵션이 제공되었습니다. 기존 FK를 삭제하고 ON DELETE CASCADE 옵션을 추가하고 FK를 다시 만든 다음 삭제를 시도했습니다.

ALTER TABLE Education ADD FOREIGN KEY (res_num) REFERENCES resumelist (res_num) 
ON DELETE CASCADE;

CASCADE 옵션을 사용하여 이력서 테이블에서 원하는 행을 삭제할 수 있었습니다. 그러나 또 다른 문제가 발견되었습니다.

가장 먼저 생각한 것은 res_num = 5인 이력서 목록에서 삭제하는 것이었습니다. 쿼리문을 실행하면 CV에서와 같이 Education/Career/Certificate 테이블에서 res_num = 5에 해당하는 행만 삭제되는 줄 알았는데 실제로는 FK res_num과 3개가 사라진다.

테이블에 저장 모든 데이터가 삭제됩니다그랬다.

2) 두 번째 시도

CASCADE 옵션이 실패한 후 TRUNCATE를 사용해 보았고 사용하기 위해 googled했습니다.

TRUNCATE로 삭제가 가능할 것 같은데 왠지 원하는 결과가 나오지 않는 것 같습니다. FK 세트.

SET foreign_key_checks = 0; // 체크 해제
DELETE TABLE (테이블명) or TRUNCATE (테이블명)
SET foreign_key_checks = 1; // 다시 체크 설정

MyBatis로 위의 프로세스를 계속 진행하는 것이 복잡하기 때문에 이 방법을 포기했습니다.

3) 마지막 시도

res_num 값과 관련된 테이블의 값을 먼저 삭제하고 resume 테이블에서 삭제를 진행하면 FK 무결성을 위반하지 않으므로 삭제할 수 있습니다.

사실 표준적인 방법이고 이미 알고 있었지만 한 문장으로 끝내고 싶은 욕심 때문에 시간을 많이 허비한 것 같습니다.

<!--	이력서 지우기 Mapper.xml	-->
<delete id="deleteResume">
    delete from resumelist where res_num = #{res_num}
</delete>
<delete id="deleteEdu">
    delete from education where res_num = #{res_num}
</delete>
<delete id="deleteWe">
    delete from workexperiences where res_num = #{res_num}
</delete>
<delete id="deleteCert">
    delete from certificate where res_num = #{res_num}
</delete>

3. 느낀 점

표준적인 방법만 사용했더라면 3~4시간을 허비하지 않았을 텐데 한 줄의 코드로 끝내려다 너무 많은 시간을 허비한 것 같습니다.

그럼에도 불구하고 데이터를 삭제할 때 FK 무결성을 염두에 두어야 함을 알 수 있었고 SQL의 기본 문법뿐만 아니라 다른 문법도 공부해야 할 필요성을 느꼈습니다. (캐스케이드, 잘라내기 등…)

코드가 복잡했지만 데이터를 지울 수 있었습니다. 하지만… 코드를 줄이고 싶은 마음은 여전해서 시간이 나면 리팩토링하는 방법을 찾아봐야겠다.