web-dev-qa-db-ja.com

postgres 9.5でアップサートを正しく行う方法

postgresql 9.5でのupsertの正しい構文、以下のクエリはcolumn reference "gallery_id" is ambiguousエラー、なぜですか?

var dbQuery = `INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id)
  DO UPDATE SET
  category_id = $1,
  last_modified_date = $3,
  last_modified_by_user_id = $4
  WHERE gallery_id = $2`;

変更しようとしましたWHERE gallery_id = $2;からWHERE category_gallery.gallery_id = $2;はエラーを表示しますthere is no unique or exclusion constraint matching the ON CONFLICT specification、しかしgallery_idまたはcategory_idを一意に設定したくない両方の列が同じであることを確認してから更新を行うため...

Postgres 9.5でアップサートを正しく行う方法は?

if ON CONFLICT一意の列が必要ですが、他の方法を使用する必要がありますか?



複数の列の両方が競合していることを確認してから更新を行いたいのですが、正しい使い方は何ですか

var dbQuery = `INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id, gallery_id)
  DO UPDATE SET
  category_id = $1,
  last_modified_date = $3,
  last_modified_by_user_id = $4
  WHERE gallery_id = $2`;


var dbQuery = `INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id AND gallery_id)
  DO UPDATE SET
  category_id = $1,
  last_modified_date = $3,
  last_modified_by_user_id = $4
  WHERE gallery_id = $2`;

テーブル(category_id、gallery_idは一意の列ではありません)

category_id | gallery_id | create_date | create_by_user_id | last_modified_date | last_modified_by_user_id
1 | 1 | ...  
1 | 2 | ...
2 | 2 | ...
1 | 3 | ...
27
user1575921

ON CONFLICTコンストラクトを使用するには、UNIQUE制約が必要です。 INSERT .. ON CONFLICT

オプションのON CONFLICT句は、一意違反または除外制約違反エラーを発生させる代替アクションを指定します。挿入が提案された個々の行ごとに、挿入が続行されるか、conflict_targetで指定されたアービター制約またはインデックスに違反した場合、代替のconflict_actionが実行されます。 ON CONFLICT DO NOTHINGは、代替アクションとして行を挿入することを単に回避します。 ON CONFLICT DO UPDATEは、代替アクションとして挿入が提案された行と競合する既存の行を更新します。

さて、質問はあまり明確ではありませんが、おそらく2列を結合したUNIQUE制約が必要です:(category_id, gallery_id)

ALTER TABLE category_gallery
    ADD CONSTRAINT category_gallery_uq
    UNIQUE (category_id, gallery_id) ;

挿入する行がbothの値と一致し、テーブルにすでに行がある場合、INSERTの代わりにUPDATEを実行します。

INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  ON CONFLICT (category_id, gallery_id)
  DO UPDATE SET
    last_modified_date = EXCLUDED.create_date,
    last_modified_by_user_id = EXCLUDED.create_by_user_id ;

UNIQUE制約のいずれかの列を使用できます。

  ON CONFLICT (category_id, gallery_id) 

または制約名:

  ON CONFLICT ON CONSTRAINT category_gallery_uq  
52
ypercubeᵀᴹ

現在受け入れられている答え の簡略化された代替として、テーブルの作成時にUNIQUE制約を匿名で追加できます。

CREATE TABLE table_name (
    id  TEXT PRIMARY KEY,
    col TEXT,
    UNIQUE (id, col)
);

次に、upsertクエリは次のようになります(既に回答されたものと同様)。

INSERT INTO table_name (id, col) VALUES ($1, $2)
ON CONFLICT (id, col)
    DO UPDATE SET col = $2;
5
Erik