sirve - postgresql vs mysql
Insertar si no existe, de lo contrario, devolver id en postgresql (3)
Tengo una tabla simple en PostgreSQL que tiene tres columnas:
- clave principal serial de identificación
- clave varchar
- valor varchar
Ya he visto esta pregunta aquí en SO: Insert, en la actualización duplicada en PostgreSQL? pero me pregunto cómo obtener la identificación si existe, en lugar de actualizar. Si la práctica estándar es siempre "insertar" o "actualizar si existe", ¿por qué? ¿El costo de hacer un SELECCIONAR (LÍMITE 1) es mayor que hacer una ACTUALIZACIÓN?
Tengo el siguiente código
INSERT INTO tag
("key", "value")
SELECT ''key1'', ''value1''
WHERE
NOT EXISTS (
SELECT id,"key","value" FROM tag WHERE key = ''key1'' AND value = ''value1''
);
que funciona en el sentido de que no se inserta si existe, pero me gustaría obtener la identificación. ¿Existe una cláusula de "RETORNO de identificación" o algo similar que pueda tocar ahí?
Sí, está returning
INSERT INTO tag ("key", "value")
SELECT ''key1'', ''value1''
WHERE NOT EXISTS (
SELECT id, "key", "value"
FROM node_tag
WHERE key = ''key1'' AND value = ''value1''
)
returning id, "key", "value"
Para devolver la fila si ya existe
with s as (
select id, "key", "value"
from tag
where key = ''key1'' and value = ''value1''
), i as (
insert into tag ("key", "value")
select ''key1'', ''value1''
where not exists (select 1 from s)
returning id, "key", "value"
)
select id, "key", "value"
from i
union all
select id, "key", "value"
from s
Si la fila no existe, devolverá el insertado más el existente.
Por cierto, si el par "clave" / "valor" lo hace único, entonces es la clave principal, y no hay necesidad de una columna de identificación. A menos que uno o ambos pares de "clave" / "valor" puedan ser nulos.
Y puede almacenar el valor devuelto a las variables en forma de ... DEVOLVER campo1, campo2, ... EN var1, var2, ...
DEVOLVER devolverá normalmente una consulta que devolverá Error ''la consulta no tiene destino para los datos de resultado'' si la llama en plpgsql sin usar su conjunto de resultados devuelto.
with vals as (
select ''key5'' as key, ''value2'' as value
)
insert into Test1 (key, value)
select v.key, v.value
from vals as v
where not exists (select * from Test1 as t where t.key = v.key and t.value = v.value)
returning id