uju's Tech

[PostgreSQL] 데이터가 존재할 때만 INSERT 본문

Node

[PostgreSQL] 데이터가 존재할 때만 INSERT

ujusy 2022. 3. 24. 19:09

<본 포스팅은 기록용으로 작성되었습니다. 혹시 틀린 부분이 있거나 문제가 되는 부분이 있다면 답글 달아주세요!>

흔히 데이터를 삽입이 필요한 API 를 구현할 때 아래와 같은 흐름으로 많이 구현한다.

 

1. 존재 여부 check

         2. 존재하지 않으면 error

3. 존재하면 insert

 

이런 로직이 당연하다고 생각하였는데 구현하고있는 대상에 따라 다른 로직을 고려해볼 수 있을 것 같다.

 

예를 들어 좋아요 생성 API 를 구현한다고 해보자.

위와 같은 로직으로 작성했을 때 생기는 엣지 케이스를 생각해보자.

 

- 네트워크 지연으로 인해 API 호출이 쌓여 동시에 찌르는 경우

- 창을 동시에 띄우고 하나의 창에 좋아요 누른 후 다른 창에도 요청하는 경우

등이 있는데 이런 경우 critical 한 부분이 아닌데도 에러를 보내는 것은 비효율적이다.

 

실제로 동시에 api를 호출하면 db 에서 duplicated 에러가 발생하는데 critical한 정보가 아니면

무조건 Insert를 해서 존재하는 경우 아무런 동작없이 리턴을

존재하지 않는 경우에는 Insert 후 id를 리턴받는 식으로 하여 Inesrt가 발생할 경우 추가 작업 진행 후 리턴 .

이러한 방식으로 개발할 수 있다.

물론 데이터베이스 리소스를 더 잡아먹을 수 있다는 side effect도 있지만 그런 동시에 발생하는 요청이 정상 대비 높은 비율이 아니라고 예측가능해서 개발자가 판단해서 진행하면 될 것 같다.

 

아래 쿼리 같은 경우 constraint가 존재할 시 do nothing. 존재하지 않아 insert를 실행할 시 id를 리턴해주고있다.

constraint뿐만아니라 column기준으로 체크할 수도있다.

INSERT INTO like (cl1) VALUE (1)
ON CONFLICT ON CONSTRAINT 'constraint 이름'
DO NOTHING
RETURNING "id"

 

아래 문서를 참고하자. 문서에 지원하는 PostgreSQL 버전 옵션이 정리되어있다.

 

https://www.postgresql.org/docs/9.5/sql-insert.html

 

INSERT

INSERT Name INSERT -- create new rows in a table Synopsis [ WITH [ RECURSIVE ] with_query [, ...] ] INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ] { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query } [ ON CONF

www.postgresql.org

 

Comments