어디서 많이 본 것 같은 데 무언가 이상하다. INSERT 도 아닌것이 UPDATE 도 아니고...
맞다. 이 두개를 합쳐 놓은 것(UPDATE + INSERT)이 UPSERT 이다.
우리가 DB 를 사용하다보면 어떤 row 는 INSERT, 어떤 row 는 UPDATE 를 하는 것과 같이 INSERT 와 UPDATE 가 섞여서 이루어져야 할 때가 있다. 이를 UPSERT 라고 부르게 된다.
INSERT INTO student (
id,
name,
age
) VALUES ${sql.join(insertQuery, sql`, `)}
ON CONFLICT (id)
DO ...
UPDATE 를 하는 경우는 ON CONFLICT
가 났을 경우이다.
ON CONFLICT (id)
와 같이 특정 컬럼에서 충돌이 났을 때 취할 행동(DO
)을 정의 할 수 있다.
이는
DO NOTHING
과 같이 아무것도 하지 않거나,DO UPDATE SET ~
과 같이 특정 열을 업데이트 할 수 있다.DO UPDATE SET ~
구문을 한번이라도 사용해본 사람은 한가지 의문이 들것이다.
'업데이트 할 값을 어떻게 접근해서 가져오지..?'
이 질문에 답을 해보자.
우리가 업데이트시 사용 할 수 있는 값에는 두가지가 있다.
1. 기존의 데이터
2. 새로 INSERT 하는 데이터
위에 예시를 다시 보자.
INSERT INTO student (
id,
name,
age
) VALUES ${sql.join(insertQuery, sql`, `)}
ON CONFLICT (id)
DO UPDATE
SET id = 'conflict made here' || student.id
기존의 데이터를 사용하길 원한다면 상단과 같이 <table>.<col>
로 접근하면 된다.
그렇다면 INSERT 한 데이터를 사용하고 싶은 경우엔?
사실, 1번 경우보다는 이 2번 경우가 훨씬 더 많을 것이다. 이때엔, 우리의 postgres 가 준 선물, EXCLUDED
를 사용하면 해결된다.
INSERT INTO student (
id,
name,
age
) VALUES ${sql.join(insertQuery, sql`, `)}
ON CONFLICT (id)
DO UPDATE
SET id = EXCLUDED.id