postgresqlでupdate insert
ある条件に当てはまるデータが登録済みならupdate、なければinsertをしたい。
結論からいうとONCONFLICTを使えばよいです。
ONCONFLICT
ONCONFLICTが使えるのはPostgresql 9.5以上、
ONCONFLICTに指定する項目はUNIQUE制約である必要があります。
INSERT INTO test_table( id , point , time ) VALUES ( '1' , 100 , '2020/08/20 10:00:00.000' ) ON CONFLICT(id) DO UPDATE SET point = 100;
CTE
ONCONFLICTが使えない場合は、CTEを使うことで同じことができます。
WITH new_values (id, point, time) as ( values ('1', 100, '2020/08/20 10:00:00.000'::timestamp) ), upd AS (UPDATE test_table SET point = 100 WHERE id = '1' RETURNING *) INSERT INTO test_table(id, point, time) SELECT (id, point, time FROM new_values WHERE not exists (SELECT id FROM upd where upd.id = new_values.id);
ただし、UNIQUE制約がついてないため、重複する可能性があります。
重複が許されないシステムの場合、ONCONFLICTが使えるようにテーブル設計変更をおすすめします。
参考
- PostgreSQLで「あればUPDATE、なければINSERT」のUPSERTをやってみる
- PostgreSQL 9.5 UPSERTを試してみた - 日々の記録 別館
- PostgreSQLでのUPSERT(INSERT or UPDATE)処理を検証する - ほんじゃらねっと
- https://www.it-swarm.dev/ja/sql/postgresql%E3%81%A7%E3%81%AE%E9%87%8D%E8%A4%87%E6%9B%B4%E6%96%B0%E6%99%82%E3%81%AB%E6%8C%BF%E5%85%A5%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B%EF%BC%9F/967270633/