web-dev-qa-db-fra.com

Comment faire correctement upsert dans Postgres 9.5

syntaxe correcte de upsert avec postgresql 9.5, la requête ci-dessous 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 ($1, $2, $3, $4)
  ON CONFLICT (category_id)
  DO UPDATE SET
  category_id = $1,
  last_modified_date = $3,
  last_modified_by_user_id = $4
  WHERE gallery_id = $2`;

J'ai essayé de changer WHERE gallery_id = $2; à WHERE category_gallery.gallery_id = $2; affiche alors 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 m'assurer que les deux colonnes sont identiques, puis mettre à jour ....

Comment faire correctement upsert dans Postgres 9.5?

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



Je veux m'assurer que plusieurs colonnes sont en conflit, puis mettre à jour, quelle est l'utilisation correcte

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


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

table (category_id, gallery_id pas une colonne unique)

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 | ...
27
user1575921

La construction ON CONFLICT Nécessite une contrainte UNIQUE pour fonctionner. De la documentation sur clause INSERT .. ON CONFLICT :

La clause facultative ON CONFLICT Spécifie une action alternative à la levée d'une contrainte d'exclusion unique ou erreur de violation. Pour chaque ligne individuelle proposée pour l'insertion, l'insertion se poursuit ou, si une contrainte ou un index arbitre spécifié par conflict_target est violé, l'autre conflict_action est prise. ON CONFLICT DO NOTHING Évite simplement d'insérer une ligne comme action alternative. ON CONFLICT DO UPDATE Met à jour la ligne existante qui entre en conflit avec la ligne proposée pour l'insertion en tant qu'action alternative.

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 aux deux valeurs avec une ligne déjà sur la table, alors au lieu de INSERT, faites une UPDATE:

INSERT INTO category_gallery (
  category_id, gallery_id, create_date, create_by_user_id
  ) VALUES ($1, $2, $3, $4)
  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 soit les colonnes de la contrainte UNIQUE:

  ON CONFLICT (category_id, gallery_id) 

ou le nom de la contrainte:

  ON CONFLICT ON CONSTRAINT category_gallery_uq  
52
ypercubeᵀᴹ

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 (similaire à ce qui a déjà été répondu):

INSERT INTO table_name (id, col) VALUES ($1, $2)
ON CONFLICT (id, col)
    DO UPDATE SET col = $2;
5
Erik