- 1. 概要
- 2. ON CONFLICT
- 3. 複数キー
1. 概要
デーブルに同値のものがなければ「INSERT」、あれば「UPDATE」したい。
よくある場面です。
初歩のころは、同値のものがあったら、いったん「DELETE」して「INSERT」していましたが・・・。
これには、いろいろな方法があるようです。
本ページは、下記のサイトを参考にさせていただきました。
「PostgreSQL で「あれば UPDATE、なければ INSERT」の UPSERT をやってみる」
「主キーの有無により insert と update を切り替えるには merge を活用する #SQL」
「UPSERT 大全2022」
2. ON CONFLICT
「postgreSQL 9.5」以上であれば、使えます。
というか、2023年11月9日時点では、これしか知りませんでした。
「postgreSQL」のドキュメントでは「INSERT」に記載があります。
INSERT INTO
テーブル
(カラム1, カラム2...)
VALUES
(値1, 値2...)
ON CONFLICT
(カラム1)
DO UPDATE
SET
カラム2 = 値2...;
てな感じで思い通りのことができるようです。
おを、便利。
ただし、参考サイトにあるように、「CONFLICT」で比較するカラムはユニークでないととんでもないことになるかエラーになります。
まぁ、通常はプライマリキーで使うのでしょう。
「ON CONFLICT」に指定できるカラムが1つかないみたいなので、困ったなぁと思っていたら・・・。
「PostgreSQL 9.5 の新機能 CONFLICT(UPSERT)を使ってみた。」を読むと、カラムを省略すると一意規約違反となる組み合わせを含む・・・ということのようです。
3. 複数キー
前項の最後の分、2024年11月11日に試してみました。
複数キーであれば、できるようです。
下記で作成したテーブル。
create table sample
(index integer not null,
name text not null,
age integer not null);
alter table sample add constraint sample_key primary key(index, name);
データとして、下記が存在している状態で。
index | name | age
-------+----------+-----
1 | hogehoge | 19
2 | fugafuga | 20
3 | piyopuyo | 21
下記を実行すると。
insert into sample
(index, name, age)
values
(1, 'hogehoge', 23)
on conflict
(index, name)
do update set age = 23;
下記の状態になりました。
index | name | age
-------+----------+-----
2 | fugafuga | 20
3 | piyopuyo | 21
1 | hogehoge | 23
|
|