오늘의 삽질... 에러모음
[MySQL] Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails...
요호유후
2025. 1. 22. 22:05
반응형
오늘의 에러
Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails...
에러사항
실습 문제 풀이 중 아래와 같이 에러가 발생했다.
실습 문제)
고객 ID가 5인 고객의 주소를 '123 New Address, New City'로 변경하시오.
작성한 쿼리문)
UPDATE customer
SET address_id = CASE
WHEN (SELECT address_id FROM address WHERE address = '123 New Address, New City') IS NULL THEN 0 ELSE (SELECT address_id FROM address WHERE address = '123 New Address, New City')
END
WHERE customer_id = 5;
에러)
Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails (`sakila`.`customer`, CONSTRAINT `fk_customer_address` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`) ON DELETE RESTRICT ON UPDATE CASCADE)
에러원인
해당 에러는 참조테이블에 없는 값을 할당했기 때문에 발생하는 것이다.
참조 무결성에 따라서 부모키에 해당하는 값만 넣을 수 있다.
+ 참조 무결성)
- 기본키와 참조키 간의 관계가 항상 유지됨을 보장한다.
- 참조되는 테이블의 행은, 이를 참조하는 참조키가 존재하는 한 삭제될 수 없고 기본키도 변경될 수 없다.
아래에 빨간색 글씨로 표시한 부분이 문제였다.
작성한 쿼리문)
UPDATE customer
SET address_id = CASE
WHEN (SELECT address_id FROM address WHERE address = '123 New Address, New City') IS NULL THEN 0 ELSE (SELECT address_id FROM address WHERE address = '123 New Address, New City')
END
WHERE customer_id = 5;
작성한 쿼리문 세번째 라인을 뜯어보면,
WHEN (SELECT address_id FROM address WHERE address = '123 New Address, New City') IS NULL THEN 0
() 안의 값이 NULL(값이 없다면) 이면 address_id = 0 으로 업데이트 하라는 뜻이다.
근데 아래의 첨부한 테이블을 보면 address_id 는 1부터 시작한다. 0의 값이 없다.
즉, 참조무결성을 위배하는 쿼리문을 짠것...
해결
이때 해결 방법으로는,
1. 참조하는 테이블에 먼저 값을 추가한다.
2. 참조하는 테이블에 존재 하는 값으로 할당한다.
3. foreign_key_checks = 0을 사용하여 FK제약을 임시로 해제한다.
(사용 후 무.조.건 foreign_key_checks = 1을 해줘야한다. 무!조!건)
위 해결 방법 중 2, 3번을 진행해 보았다. (1번은 언젠가 심심하면 해봐야즹)
나는 지금 실습 중이기때문에 2, 3번으로 진행해도 무방하겠지만
나중에 실제 서비스를 작성해야할 경우에는 1번 혹은 3번도 괜찮겠지??
2번 : 그냥 단순히 존재하는 값으로 변경
(문제의 address = '123 New Address, New City' 내용은 무시)
UPDATE customer
SET address_id = CASE
WHEN (SELECT address_id FROM address WHERE address = '123 New Address, New City') IS NULL THEN 1
ELSE (SELECT address_id FROM address WHERE address = '123 New Address, New City')
END
WHERE customer_id = 5;
3번 : 쿼리문 위 아래 라인에 foreign_key_checks 를 비활성/활성 해준다.
SET foreign_key_checks = 0;
UPDATE customer
SET address_id = CASE
WHEN (SELECT address_id FROM address WHERE address = '123 New Address, New City') IS NULL THEN 0
ELSE (SELECT address_id FROM address WHERE address = '123 New Address, New City')
END
WHERE customer_id = 5;
SET foreign_key_checks = 1;
+ foreign_key_checks 사용 시 주의사항
foreign_key_checks 의 설정은 FK 제약과 상관없이 쿼리문을 수행하게 해준다.
따라서, 이후 실행된 쿼리문들이 FK제약에 위반된 테이블 혹은 데이터를 생성할 수 있다는 것!!
그래서
1. 단순 테스트 코드나 일회성? 코드를 작성할 때 사용하거나
2. FK제약에 위반된 테이블 혹은 데이터를 생성한 후 위반사항들을 처리해주자!
(예를 들어 자식테이블에 부모테이블에 없는 값을 억지로? 생성/갱신 하였다면,
이후 부모테이블에도 해당값을 데이터로 생성해주자!)
글을 정리하며...
은근 까다롭다 쿼리의 세계.... 근데 재밌당 > <
참고링크
반응형