Donné:
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)
);
Cette requête:
insert into table_b (pk_b, b)
select pk_a,a from table_a
on conflict (b) do update set b=a;
provoque l'erreur suivante:
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.
Comment faire la mise à jour en se référant au contenu de table_a
?
Problèmes multiples.
Votre configuration, étendue:
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');
Cela marche:
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
Résultat:
TABLE b;
pk_b | b | comment
------+----+----------------
1 | 11 | comment from b -- updated
2 | 22 | comment from a -- inserted
Vous confondez table_a
Et A
dans votre démo (comme @ Abelisto a commenté ).
L'utilisation d'identificateurs légaux, minuscules et non cotés aide à éviter toute confusion.
Comme @ Ziggy mentionné , ON CONFLICT
Ne fonctionne que pour les violations réelles de contraintes uniques ou d'exclusion . Le manuel:
La clause facultative
ON CONFLICT
Spécifie une action alternative pour déclencher une erreur de violation de contrainte d'exclusion ou de violation unique.
Par conséquent, ne peut pas fonctionner, aucune contrainte là-bas. ON CONFLICT (b)
ON CONFLICT (pk_b)
fonctionne.
Comme @ Ziggy également mentionné , source les noms de table ne sont pas visibles dans le UPDATE
part. Le manuel:
Les clauses
SET
etWHERE
dansON CONFLICT DO UPDATE
Ont accès à la ligne existante en utilisant le nom de la table (ou un alias), et aux lignes proposé pour l'insertion en utilisant la table spécialeexcluded
.
Accentuation sur moi.
Vous ne pouvez pas non plus utiliser les noms de colonne de la table source dans la partie UPDATE
. Il doit s'agir des noms de colonne de la ligne cible. Vous voulez donc vraiment:
SET b = excluded.b
Notez que les effets de tous les déclencheurs
BEFORE INSERT
Par ligne sont reflétés dans les valeurs exclues, car ces effets peuvent avoir contribué à exclure la ligne de l'insertion.
Lorsque vous effectuez des upserts dans PostgreSQL 9.5+, vous devez vous référer aux données exclues (celles qui n'ont pas pu être insérées) par l'alias excluded
. Également on conflict
l'option doit faire référence à la clé: (pk_b)
plutôt que (b)
. Par exemple.
insert into table_b (pk_b, b)
select pk_a,a from table_a
on conflict (pk_b) do update set b=excluded.b;
Pour plus d'informations, reportez-vous à la documentation officielle ou cette introduction facile à upsert .