次のようなテーブルがあります。
CREATE TABLE aggregated_master (
"user" BIGINT,
type TEXT,
date TIMESTAMP,
operations BIGINT,
amount NUMERIC,
PRIMARY KEY ( "user", type, date )
);
このテーブルは、多くのパーティションが継承するマスターです。パーティションは、DATEフィールドのMONTHによって行われます。たとえば、Aug-2017のパーティションはagg_201708で、そのPKはpk_agg_201708になります。挿入を適切なパーティションにリダイレクトする通常のトリガーBEFORE INSERTがあります。
事は私がこのテーブルにUPSERTをしたいということです。 DO CONFLICT部分が機能していません。
最初のコードはこのようなものでした
INSERT INTO aggregated_master (user, type, date, oeprations, amount)
SELECT user, type, date, SUM(ops), SUM(amt)
FROM ...
WHERE ...
GROUP BY USER, TYPE, DATE
ON CONFLICT ON CONSTRAINT pk_aggregated
DO UPDATE SET operations = EXCLUDED.operations
, amount = EXCLUDED.amount
しかしその後、制約(pk_aggregated)がマスターテーブルの制約であり、トリガーが原因で実際に挿入が実行される子テーブルの制約ではないことに気付きました。
CONFLICT句を次のように変更しました。
ON CONFLICT (user, type, date)
これはPKのフィールドですが、これも機能しません。
これを機能させる方法はありますか?
PostgreSQL 11は、パーティションテーブルでINSERT INTO ... ON CONFLICT
をサポートしています。
CREATE TABLE o(id INT PRIMARY KEY, i INT) PARTITION BY RANGE (id);
CREATE TABLE o1 PARTITION OF o FOR VALUES FROM (1) TO (1000);
CREATE TABLE o2 PARTITION OF o FOR VALUES FROM (1000) TO (2000);
INSERT INTO o(id, i) VALUES (1,1),(2,2),(1500,1500);
INSERT INTO o(id, i)
VALUES (1500, 1400), (2,20), (3, 3)
ON CONFLICT (id)
DO UPDATE SET i = EXCLUDED.i;
SELECT * FROM o;
5.10.2.3。制限事項
パーティション化されたテーブルでON CONFLICT句を使用すると、エラーが発生します。一意制約または除外制約は、個々のパーティションでのみ作成できるためです。パーティション階層全体で一意性(または除外制約)を適用することはサポートされていません。
解除されました。
Postgres 11より前のバージョンでは、パーティションテーブルのアップサートは実装されていません。
ON CONFLICT句を含むINSERTステートメントは期待どおりに機能しない可能性があります。ONCONFLICTアクションは、指定されたターゲットリレーションで一意の違反が発生した場合にのみ実行され、その子リレーションでは発生しないためです。
宣言的なパーティション分割では問題は解決されません、 Postgres 10:
パーティション化されたテーブルでON CONFLICT句を使用すると、エラーが発生します。一意制約または除外制約は、個々のパーティションでのみ作成できるためです。パーティション階層全体で一意性(または除外制約)を適用することはサポートされていません。
("user", type, date)
すべての子テーブルで、Postgres 11ではON CONFLICT
パーティションテーブルについては、 lad2025の回答を参照してください。