스터디를 하던 도중 다음과 같은 질문을 받았다.
"중복값이 이미 존재하는 Column에 PK constraint를 추가하면 어떻게 될까요?"
일반적인 상식으로는 당연히 PK는 강력한 constraint라서 안 걸릴거라고 생각할 수도 있지만, 애매하게 아는게 무섭다고... 이전에 배운 constraint 적용 시점에 대해서 명확하게 알지 못했기 때문에 혹시 중복된 값이 있더라도 이전 시점이면 걸릴 수 있지 않을까 하고 잘못된 답변을 했었다.
일단 결론부터 말하자면, 걸리지 않는다!
우선, PK의 기본적 특성을 살펴보자.
즉, 질문에 해당하는 상황에서는 unique constraint와 충돌이 발생한다.
그 다음으로 제약조건에 대해 알아보자
제약조건은 총 4가지가 존재한다.
| Modfied Data | Existing Data | Desc |
|---|---|---|
| ENABLE | VALIDATE | 이미 존재하는 값과 앞으로 들어올 값들이 모두 constraint를 준수해야한다. |
| ENABLE | NOVALIDATE | 새로 들어올 값만 constraint를 준수하면 된다. 따라서 이미 존재하는 값은 constraint를 위반할 수 있다. |
| DISABLE | VALIDATE | constraint를 해제하고 해당 칼럼을 더이상 수정이 불가능하게 한다. 이때 인덱스도 버린다. |
| DISABLE | NOVALIDATE | constraint를 아예 해제한 경우이다. |
내가 생각했던 바로는 PK는 ENABLE,NOVALIDATE 방식으로 동작할 것 같았지만, ENABLE,VALIDATE 방식으로 동작한다.
실제로 코드를 실행하면 다음과 같이 PK를 위반했다면서 적용이 되지 않는다.

심지어 PK는 NOVALIDATE 옵션도 불가능하기에 해당 칼럼에 중복값이 존재한다면 PK 선언은 아예 불가능하다고 봐야한다.
이유로는 다음과 같다. DB에서 PK constraint를 생성할 때, index를 통해 constraint를 걸어주는데, 이때 index가 unique해야 한다.
사실 조금만 생각해보면 간단한 이치이다. 무결성을 위해 제약조건을 추가하였는데, 추가된 시점부터 무결성이 깨져있다면 제약조건을 추가한 의미가 있을까..?
정말 예외적으로 deferrable constraint를 걸게 되면 만들어진 index는 unique하지 않다.
하지만 이건 트랜잭션 안에서만 가능할 뿐 트랙잭션이 다 끝나서 commit이 되면 다시 constraint를 위반한 것이기에 PK가 적용되지 않는다.
