sql >> Base de Datos >  >> RDS >> PostgreSQL

Obtener Id de un INSERT condicional

La implementación de UPSERT es enormemente compleja para estar segura contra el acceso de escritura concurrente. Eche un vistazo a este wiki de Postgres que sirvió como registro durante el desarrollo inicial. Los piratas informáticos de Postgres decidieron no incluir filas "excluidas" en el RETURNING cláusula para la primera versión en Postgres 9.5. Podrían incorporar algo para la próxima versión.

Esta es la declaración crucial en el manual para explicar su situación:

La sintaxis de RETURNING la lista es idéntica a la de la lista de salida de SELECT . Solo se devolverán las filas que se insertaron o actualizaron correctamente. Por ejemplo, si una fila se bloqueó pero no se actualizó debido a un ON CONFLICT DO UPDATE ... WHERE la condición de la cláusula no se cumplió, la fila no se devolverá.

Énfasis en negrita mío.

Para una fila única para insertar:

Sin carga de escritura simultánea en la misma tabla

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;

Con posible carga de escritura simultánea en la tabla

Considere esto en su lugar (para fila única INSERT ):

  • ¿Es SELECCIONAR o INSERTAR en una función propensa a condiciones de carrera?

Para insertar un conjunto de filas :

  • ¿Cómo usar RETURNING con ON CONFLICT en PostgreSQL?

  • Cómo incluir filas excluidas en RETURNING from INSERT... ON CONFLICT

Los tres con una explicación muy detallada.