Comment faire correctement upsert en postgres 9.5

syntaxe correcte de upsert avec postgresql 9.5, au-dessous de la requête montre column reference "gallery_id" is ambiguous erreur, pourquoi?

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

j'ai essayé de changer WHERE gallery_id = ; en WHERE category_gallery.gallery_id = ; puis affiche l'erreur there is no unique or exclusion constraint matching the ON CONFLICT specification , mais Je ne veux pas définir gallery_id ou category_id comme unique parce que je veux être sûr que les deux colonnes sont les mêmes puis faites la mise à jour....

comment faire correctement upsert en postgres 9.5?

si ON CONFLICT besoin colonne unique, dois-je utiliser une autre méthode, comment?





je veux être sûr de plusieurs colonnes les deux conflits puis faire la mise à jour, ce qui est l'usage correct

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


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

(category_id , gallery_id pas unique colonne)

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 | ...
18
demandé sur user1575921 2016-04-22 19:35:26

2 réponses

la construction ON CONFLICT nécessite une contrainte de travail UNIQUE . De la documentation sur INSERT .. ON CONFLICT clause :

la clause facultative ON CONFLICT spécifie une action alternative à la levée d'une violation unique ou contrainte d'exclusion erreur de violation. Pour chaque ligne individuelle proposée Pour insertion, l'insertion se poursuit ou, si une la contrainte d'arbitrage ou l'index spécifié par conflict_target est violé, l'alternative conflict_action est prise. ON CONFLICT DO NOTHING évite simplement d'insérer une rangée comme son action alternative. ON CONFLICT DO UPDATE met à jour la rangée existante qui est en conflit avec la rangée qu'il est proposé d'insérer à titre de solution de rechange.

maintenant, la question n'est pas très claire, mais vous avez probablement besoin d'une contrainte UNIQUE sur les 2 colonnes combinées: (category_id, gallery_id) .

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

si la ligne à insérer correspond à les deux valeurs avec une ligne déjà sur la table, alors au lieu de INSERT , faites un UPDATE :

INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES (, , , )
  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 ;

vous pouvez utiliser l'une ou l'autre des colonnes de la contrainte UNIQUE:

  ON CONFLICT (category_id, gallery_id) 

ou le nom de la contrainte:

  ON CONFLICT ON CONSTRAINT category_gallery_uq  
43
répondu ypercubeᵀᴹ 2017-07-12 08:05:24

comme alternative simplifiée à la réponse actuellement acceptée , la contrainte UNIQUE peut être ajoutée anonymement lors de la création de la table:

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

ensuite, la requête upsert devient (semblable à ce qui a déjà été répondu):

INSERT INTO table_name (id, col) VALUES (, )
ON CONFLICT (id, col)
    DO UPDATE SET col = ;
3
répondu Erik 2017-10-26 10:09:04