Ayez une table comme celle-ci:
CREATE TABLE aggregated_master (
"user" BIGINT,
type TEXT,
date TIMESTAMP,
operations BIGINT,
amount NUMERIC,
PRIMARY KEY ( "user", type, date )
);
Cette table est le maître dont héritent de nombreuses partitions. Les partitions sont effectuées par MOIS dans le champ DATE. Par exemple: la partition pour août 2017 serait agg_201708 et son PK serait pk_agg_201708 Il y a le déclencheur habituel AVANT INSERT pour rediriger l'insertion vers la partition appropriée.
Le fait est que je veux faire un UPSERT dans ce tableau. La partie DO CONFLICT ne fonctionne pas.
Le code était d'abord comme ça
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
Mais ensuite, j'ai remarqué que la contrainte (pk_aggregated) est celle de la table principale, et non de la table enfant où l'insertion sera réellement effectuée, en raison du déclencheur.
J'ai changé la clause CONFLICT en:
ON CONFLICT (user, type, date)
Quels sont les domaines du PK, mais cela ne fonctionne pas non plus.
Une idée comment faire pour que ça marche?
PostgreSQL 11 prend en charge INSERT INTO ... ON CONFLICT
avec des tables partitionnées:
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;
Limitation partitionnement ddl
5.10.2.3. Limites
L'utilisation de la clause ON CONFLICT avec des tables partitionnées provoquera une erreur, car des contraintes uniques ou d'exclusion ne peuvent être créées que sur des partitions individuelles. Il n'y a pas de prise en charge pour appliquer l'unicité (ou une contrainte d'exclusion) à travers une hiérarchie de partitionnement entière.
a été levé.
Upsert sur les tables partitionnées n'est pas implémenté dans les versions antérieures à Postgres 11.
Il est peu probable que les instructions INSERT avec des clauses ON CONFLICT fonctionnent comme prévu, car l'action ON CONFLICT n'est effectuée qu'en cas de violations uniques sur la relation cible spécifiée, et non sur ses relations enfants.
Le partitionnement déclaratif ne résout pas le problème, Postgres 10:
L'utilisation de la clause ON CONFLICT avec des tables partitionnées provoquera une erreur, car des contraintes uniques ou d'exclusion ne peuvent être créées que sur des partitions individuelles. Il n'y a pas de prise en charge pour appliquer l'unicité (ou une contrainte d'exclusion) à travers une hiérarchie de partitionnement entière.
("user", type, date)
sur toutes les tables enfants, Dans Postgres 11 , vous pouvez utiliser ON CONFLICT
sur les tables partitionnées, voir réponse de lad2025.