PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Obtenir l'ID d'un INSERT conditionnel

L'implémentation UPSERT est extrêmement complexe pour être protégée contre les accès en écriture simultanés. Jetez un œil à ce wiki Postgres qui a servi de journal lors du développement initial. Les pirates de Postgres ont décidé de ne pas inclure les lignes "exclues" dans le RETURNING clause pour la première version de Postgres 9.5. Ils pourraient créer quelque chose pour la prochaine version.

Voici l'énoncé crucial du manuel pour expliquer votre situation :

La syntaxe du RETURNING la liste est identique à celle de la liste de sortie de SELECT . Seules les lignes insérées ou mises à jour avec succès seront renvoyées. Par exemple, si une ligne a été verrouillée mais pas mise à jour en raison d'un ON CONFLICT DO UPDATE ... WHERE la condition de la clause n'était pas satisfaite, la ligne ne sera pas renvoyée.

J'insiste sur moi.

Pour une ligne unique pour insérer :

Sans charge d'écriture simultanée sur la même table

WITH ins AS (
   INSERT INTO users(name)
   VALUES ('new_usr_name')         -- input value
   ON     CONFLICT(name) DO NOTHING
   RETURNING users.id
   )
SELECT id FROM ins
UNION  ALL
SELECT id FROM users          -- 2nd SELECT never executed if INSERT successful
WHERE  name = 'new_usr_name'  -- input value a 2nd time
LIMIT  1;

Avec une charge d'écriture simultanée possible sur la table

Considérez ceci à la place (pour une seule ligne INSERT ):

  • SELECT ou INSERT est-il dans une fonction sujette à des conditions de concurrence ?

Pour insérer un ensemble de lignes :

  • Comment utiliser RETURNING avec ON CONFLICT dans PostgreSQL ?

  • Comment inclure des lignes exclues dans RETURNING from INSERT ... ON CONFLICT

Tous les trois avec des explications très détaillées.