Tengo una tabla tagcon 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 iddel registro existente.
Supuse que podría usarlo ON CONFLICT DO NOTHINGen 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 UPDATEclá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 CONFLICTsintaxis.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
tagtabla y devuelva los ID; combine eso con las ID de los nombres que existen entag, para el resultado final. También puede incluirnameen 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 ... ;