与えられた:
CREATE TABLE A (
PK_A INT8 NOT NULL,
A INT8,
PRIMARY KEY (PK_A)
);
CREATE TABLE B (
PK_B INT8 NOT NULL,
B INT8,
PRIMARY KEY (PK_B)
);
このクエリ:
insert into table_b (pk_b, b)
select pk_a,a from table_a
on conflict (b) do update set b=a;
次のエラーが発生します。
ERROR: column "a" does not exist LINE 1: ...elect pk_a,a from table_a on conflict (b) do update set b=a; ^ HINT: There is a column named "a" in table "*SELECT*", but it cannot be referenced from this part of the query.
table_a
の内容を参照しながら更新する方法は?
複数の問題。
拡張されたセットアップ:
_CREATE TABLE a (
pk_a int PRIMARY KEY
, a int
, comment text -- added column to make effect clear
);
CREATE TABLE b (
pk_b int PRIMARY KEY
, b int
, comment text
);
INSERT INTO a VALUES (1, 11, 'comment from a')
, (2, 22, 'comment from a');
INSERT INTO b VALUES (1, 77, 'comment from b');
_
これは機能します:
_INSERT INTO b (pk_b, b, comment)
SELECT pk_a, a, comment
FROM a
ON CONFLICT (pk_b) DO UPDATE -- conflict is on the unique column
SET b = excluded.b; -- key Word "excluded", refer to target column
_
結果:
_TABLE b;
pk_b | b | comment
------+----+----------------
1 | 11 | comment from b -- updated
2 | 22 | comment from a -- inserted
_
デモで_table_a
_とA
を混乱させています( @ Abelistoがコメントした など)。
正当な小文字の引用符で囲まれていない識別子を使用すると、混乱を避けることができます。
@ Ziggyについて と同様に、_ON CONFLICT
_は実際の一意または除外制約違反に対してのみ機能します。 マニュアル:
オプションの_
ON CONFLICT
_句は、一意の違反または除外制約違反エラーを発生させる代替アクションを指定します。
したがって、 機能せず、そこに制約はありません。 ON CONFLICT (b)
ON CONFLICT (pk_b)
は機能します。
@ Ziggyについても言及 と同様に、UPDATE
部分のsourceテーブル名は表示されません。 マニュアル:
_
ON CONFLICT DO UPDATE
_のSET
句とWHERE
句は、テーブルの名前(またはエイリアス)を使用して既存の行にアクセスし、特殊なexcluded
table。
大胆な強調鉱山。
また、UPDATE
部分でsourceテーブルの列名を使用することはできません。 target行の列名でなければなりません。だからあなたは本当に欲しい:
_SET b = excluded.b
_
行ごとの_
BEFORE INSERT
_トリガーの影響は、除外された値に反映されることに注意してください。これらの影響は、挿入から除外される行に寄与した可能性があるためです。
PostgreSQL 9.5以降でアップサートを実行するときは、除外されたデータ(挿入に失敗したデータ)をエイリアスexcluded
で参照する必要があります。また、on conflict
オプションはキーを参照する必要があります:(pk_b)
のではなく (b)
。例えば。
insert into table_b (pk_b, b)
select pk_a,a from table_a
on conflict (pk_b) do update set b=excluded.b;
詳細については、公式ドキュメントまたは psertの簡単な紹介 を参照してください。