[解決済み] PostgreSQLで重複して更新された場合の挿入?
2022-03-14 16:44:15
質問
数ヶ月前、Stack Overflowの回答で、以下の構文を使用してMySQLで一度に複数の更新を実行する方法を知りました。
INSERT INTO table (id, field, field2) VALUES (1, A, X), (2, B, Y), (3, C, Z)
ON DUPLICATE KEY UPDATE field=VALUES(Col1), field2=VALUES(Col2);
今、PostgreSQLに切り替えたところ、どうやらこれは正しくないようです。すべての正しいテーブルを参照しているので、異なるキーワードが使用されている問題だと思いますが、PostgreSQLのドキュメントのどこに記載があるのかわかりません。
明確にするために、私はいくつかのものを挿入し、それらがすでに存在する場合はそれらを更新したい。
どのように解決するのですか?
バージョン9.5以降のPostgreSQLには UPSERT 構文で オンコンフリクト 節があります。 を次のような構文で使用します(MySQLに似ています)。
INSERT INTO the_table (id, column_1, column_2)
VALUES (1, 'A', 'X'), (2, 'B', 'Y'), (3, 'C', 'Z')
ON CONFLICT (id) DO UPDATE
SET column_1 = excluded.column_1,
column_2 = excluded.column_2;
postgresqlのメールグループアーカイブで"upsert"を検索すると、次のようなものが見つかります。 マニュアルにある、やりたいことをやる例 :
例 38-2. UPDATE/INSERT での例外処理
この例では、例外処理を使用してUPDATEまたはINSERTのいずれかを適切に実行します。
CREATE TABLE db (a INT PRIMARY KEY, b TEXT);
CREATE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS
$$
BEGIN
LOOP
-- first try to update the key
-- note that "a" must be unique
UPDATE db SET b = data WHERE a = key;
IF found THEN
RETURN;
END IF;
-- not there, so try to insert the key
-- if someone else inserts the same key concurrently,
-- we could get a unique-key failure
BEGIN
INSERT INTO db(a,b) VALUES (key, data);
RETURN;
EXCEPTION WHEN unique_violation THEN
-- do nothing, and loop to try the UPDATE again
END;
END LOOP;
END;
$$
LANGUAGE plpgsql;
SELECT merge_db(1, 'david');
SELECT merge_db(1, 'dennis');
9.1以降でCTEを使用して一括で行う方法の例は、おそらく ハッカーズメーリングリスト :
WITH foos AS (SELECT (UNNEST(%foo[])).*)
updated as (UPDATE foo SET foo.a = foos.a ... RETURNING foo.id)
INSERT INTO foo SELECT foos.* FROM foos LEFT JOIN updated USING(id)
WHERE updated.id IS NULL;
参照 a_horse_with_no_nameさんの回答 を使うと、より分かりやすいと思います。
関連
-
PostgreSQLのURL解決方法
-
[解決済み] PostgreSQLの場合。PostgreSQLのテーブルを表示する
-
[解決済み] PostgreSQLの "DESCRIBE TABLE"
-
[解決済み] PostgreSQL コマンドラインユーティリティ: psql を終了する方法
-
[解決済み] PostgreSQLのユーザーパスワードを変更する方法を教えてください。
-
[解決済み] どのバージョンのPostgreSQLを使用していますか?
-
[解決済み] MySQLテーブルへの挿入または存在する場合の更新
-
[解決済み] SQL ServerにおけるINSERT OR UPDATEに関する解決策
-
[解決済み】Mac OS XでPostgreSQLサーバーを起動するには?
-
[解決済み】PostgreSQLでUPSERT(MERGE、INSERT ... ON DUPLICATE UPDATE)する方法とは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
PostgreSQLのJSONBのマッチングと交差の問題について
-
どのように定期的にLinux上でpostgresqlのデータベースをバックアップする
-
GROUP BY句での定数使用に関するPostgreSQLの特別な制限について説明します。
-
PostgreSQLにおけるsequence、serial、identityの使い方の違いについて
-
postgresqlのjsonbデータの問い合わせと変更方法
-
PostgreSQLで時間指定タスクを実装する4つの方法
-
[解決済み] PostgreSQL 自動インクリメント
-
[解決済み] 'ユーザー "postgres" のパスワード認証に失敗しました'
-
[解決済み] PostgreSQLでカラムのデフォルト値を変更するにはどうすればよいですか?
-
[解決済み] クエリプランにおける「ビットマップヒープスキャン」とは何ですか?