- Published on
postgresql duplicate key value violates unique constrain 에러 해결하기
- Authors
- Name
- SeongHwa Lee
- @earthloverdev
배경
postgresql db를 사용 중, backend에서 orm으로 create 명령을 실행할 때 문제가 발생했습니다. 바로 알아채지 못하고 검색이 필요했어서 앞으로 기억하기 위해 정리합니다.
문제
pg table에 row를 insert 하려고 할 때 duplicate key value violates unique constrain PK_324238724
에러가 발생합니다.
이는 쉽게 이야기하면, 내가 row를 하나 더 생성하려고 할 때, table 이 자동으로 부여하려고 하는 key가 중복된다는 뜻입니다. 다행히 이 문제를 쉽게 유추한 것은 위 테이블의 row를 제가 직접 조작한 적이 있었기 때문에, PK가 중복되는 이유는 내부의 key가 중복될 것이라 판단했기 때문입니다. 구글링을 해본 결과 역시 가장 확률이 높았고 postgresql의 sequence manipulation function을 실행해서 이 문제를 해결할 수 있었습니다.
Sequence Manipulation Functions
Sequences란?
Sequence objects are special single-row tables created with CREATE SEQUENCE.
9.17. Sequence Manipulation Functions 공식 문서
해결
-
key 이름을 찾습니다.
-- Sequence and defined type CREATE SEQUENCE IF NOT EXISTS table_id_seq; -- Table Definition CREATE TABLE "public"."table" ( "id" int4 NOT NULL DEFAULT nextval('table_id_seq'::regclass), "slug" varchar NOT NULL DEFAULT 'noname'::character varying, "description" text, "create_datetime" timestamp NOT NULL DEFAULT now(), PRIMARY KEY ("id") );
이런 식으로 create query를 조회해 보시면 table_id_seq라는 key를 알 수 있습니다.
-
select lastval() from 테이블 이름;
을 실행하면 현재 table에 설정된 key의 값을 알 수 있습니다. 보통 에러가 나는 경우에는 table에 특수한 조작으로 row를 이전에 insert해서 table 내부 table_id_seq값이 max(id)보다 작아서 이미 해당 id의 row가 존재함을 알 수 있습니다. -
select setval('table_id_seq', (select max(id) from table));
쿼리를 실행해 키의 최대값을 재설정합니다. -
이후에 아까 실행하려던 insert 쿼리를 생성하면 정상적으로 실행되는 것을 알 수 있습니다.
끝!!!
앞으로 할 일
그냥 typeorm에서는 @PrimaryGeneratedColumn()
로 선언한 컬럼이 실제로는 Sequence를 생성한다는 사실을 알았습니다. orm에 너무 의존하다 보니 이렇게 에러를 만나게 되면 해결하기 쉽지 않은데요, 이렇게 만날 때마다 공부해 놓으면 될 것 같습니다.