DB마다 insert
시 충돌이 나는 경우를 처리해주는 upsert
구현에서 차이가 많이 난다.
Example
같은 scheme을 사용하는 테이블 table_a
, table_b
가 주어졌을 때, table_b
의 값을 table_a
로 upsert하는 SQL을 살펴보자.
SQL OnLine IDE에서 실습이 가능하다!
id
가 같은 경우,INT
column은 더하고,DATE
column은 더 최근값으로 업데이트
CREATE TABLE
table_a (
id INT PRIMARY KEY,
a INT,
b INT,
date DATE);
INSERT INTO
table_a
VALUES
(1, 1, 2, '2020-01-01'),
(2, 3, 4, '2020-02-01'),
(3, 5, 6, '2020-03-01');
CREATE TABLE
table_b (
id INT PRIMARY KEY,
a INT,
b INT,
date DATE);
INSERT INTO
table_b
VALUES
(3, 10, 20, '2020-04-01'),
(4, 30, 40, '2020-05-01');
Input
-
table_a
id a b date 1 1 2 2020-01-01 2 3 4 2020-02-01 3 5 6 2020-03-01 -
table_a
id a b date 3 10 20 2020-04-01 4 30 40 2020-05-01
Output
-
table_a
id a b date 1 1 2 2020-01-01 2 3 4 2020-02-01 3 15 26 2020-04-01 4 30 40 2020-05-01
1. PostgreSQL
INSERT INTO
table_a (id, a, b, date)
SELECT
b.id,
b.a,
b.b,
b.date
FROM
table_b AS b
ON CONFLICT
(id)
DO UPDATE SET
a = table_a.a + EXCLUDED.a,
b = table_a.b + EXCLUDED.b,
date = GREATEST(table_a.date, EXCLUDED.date);
ON CONFLICT
구문은PostgreSQL 9.5
이상의 버전에서만 지원됨- 일반적으로 사용되는
ON CONFLICT
구문은 다음과 같은 형태를 가진다. (doc)INSERT INTO table_name VALUES (...) ON CONFLICT [conflict_target] conflict_action
conflict_target
(columns)
columns
를 기준으로 중복 체크 (위 예시)ON CONSTRAINT constraint
constraint
를 기준으로 중복 체크
conflict_action
DO NOTHING
아무 것도 하지 않음DO UPDATE SET
조건에 해당되는 column을 업데이트 (위 예시)
- 관련된 몇 가지 예시들은 다음 링크를 참고
https://dbfiddle.uk/l0dNf3hO
References
PREVIOUSEtc