Published on

postgresql duplicate key value violates unique constrain 에러 해결하기

Authors

배경

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 공식 문서

해결

  1. 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를 알 수 있습니다.

  2. select lastval() from 테이블 이름; 을 실행하면 현재 table에 설정된 key의 값을 알 수 있습니다. 보통 에러가 나는 경우에는 table에 특수한 조작으로 row를 이전에 insert해서 table 내부 table_id_seq값이 max(id)보다 작아서 이미 해당 id의 row가 존재함을 알 수 있습니다.

  3. select setval('table_id_seq', (select max(id) from table)); 쿼리를 실행해 키의 최대값을 재설정합니다.

  4. 이후에 아까 실행하려던 insert 쿼리를 생성하면 정상적으로 실행되는 것을 알 수 있습니다.

끝!!!

앞으로 할 일

그냥 typeorm에서는 @PrimaryGeneratedColumn() 로 선언한 컬럼이 실제로는 Sequence를 생성한다는 사실을 알았습니다. orm에 너무 의존하다 보니 이렇게 에러를 만나게 되면 해결하기 쉽지 않은데요, 이렇게 만날 때마다 공부해 놓으면 될 것 같습니다.