UPDATE 時のインクリメントがうまくいくからといって、
アップサートでのインクリメントが同じ構文では効かないのが PostgresSQL
こんなテーブルがあった時、
CREATE TABLE ITEMS ( ID VARCHAR(6), NAME VARCHAR(20), U_COUNT INTEGER, PRIMARY KEY (id) )
これは期待どおりインクリメントする。
UPDATE ITEMS SET U_COUNT = U_COUNT + 1 WHERE ID = 2
でも、以下はダメ!
INSERT INTO ITEMS(ID, NAME, U_COUNT) VALUES (10, 'ABC', 0) ON CONFlICT (ID) DO UPDATE SET U_COUNT = U_COUNT + 1 RETURNING U_COUNT
マニュアルを見ると、
PostgreSQL: Documentation: 12: INSERT
The SET and WHERE clauses in ON CONFLICT DO UPDATE have access to the existing row using the table's name (or an alias), and to the row proposed for insertion using the special excluded table
ON CONFLICT DO UPDATE の SET 句と WHERE 句は、テーブルの名前 (または別名) を
使用して既存の行にアクセスし、特別なexcludedテーブルを使ってアクセスできます
ということだ。
だから、以下のようにすると期待どおりになる。
INSERT INTO ITEMS(ID, NAME, U_COUNT) VALUES (10, 'ABC', 0) ON CONFlICT (ID) DO UPDATE SET U_COUNT = ITEMS.U_COUNT + 1 RETURNING U_COUNT