Tengo una tabla tag
con 2 columnas: id
(uuid) y name
(texto). Ahora quiero insertar una nueva etiqueta en la tabla, pero si la etiqueta ya existe, simplemente quiero obtener la id
del registro existente.
Supuse que podría usarlo ON CONFLICT DO NOTHING
en combinación con RETURNING "id"
:
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT DO NOTHING
RETURNING "id";
Pero esto devuelve un conjunto de resultados vacío, si la etiqueta con el nombre "foo" ya existe.
Luego cambié la consulta para usar una DO UPDATE
cláusula noop :
INSERT INTO
"tag" ("name")
VALUES( 'foo' )
ON CONFLICT ("name") DO UPDATE SET "name" = 'foo'
RETURNING "id";
Esto funciona según lo previsto, pero es algo confuso, porque solo estoy configurando el nombre al valor ya existente.
¿Es esta la forma de solucionar este problema o me falta un enfoque más simple?
postgresql
upsert
postgresql-9.5
Der Hochstapler
fuente
fuente
returning excluded.id
?ERROR: missing FROM-clause entry for table "excluded"
cuando lo usoDO NOTHING
.Respuestas:
Esto funcionará (por lo que probé) en los 3 casos, si los valores a insertar son todos nuevos o todos ya están en la tabla o una mezcla:
Probablemente hay otras formas de hacer esto, tal vez sin usar la nueva
ON CONFLICT
sintaxis.fuente
No tengo idea de cómo funcionará esto, pero solo como otra opción para intentar, aquí está haciendo lo mismo de la vieja escuela (sin
ON CONFLICT
):Es decir, inserte solo los nombres [únicos] que no se encuentran en la
tag
tabla y devuelva los ID; combine eso con las ID de los nombres que existen entag
, para el resultado final. También puede incluirname
en la salida, como lo sugiere ypercubeᵀᴹ , para que sepa qué ID coincide con qué nombre.fuente
SELECT .. FROM ins UNION ALL SELECT ... FROM val JOIN tag ... ;