El INSERT
simplemente insertará todas las filas y nada ocurrirá algo especial, a menos que tienes algún tipo de restricción no permitir valores duplicados/superpuestos (PRIMARY KEY
, UNIQUE
, CHECK
o EXCLUDE
restricción) - que no mencionó en su pregunta. Pero eso es lo que probablemente le preocupa.
Asumiendo un UNIQUE
o restricción PK en (col1,col2)
, se trata de un libro de texto UPSERT
situación. Muchas preguntas y respuestas relacionadas para encontrar aquí.
Generalmente, si cualquiera se viola la restricción, se genera una excepción que (a menos que esté atrapada en una subtransacción como es posible en un lenguaje de procedimiento del lado del servidor como plpgsql) revertirá no solo la declaración, sino la transacción completa .
Sin escrituras simultáneas
Es decir:ninguna otra transacción intentará escribir en la misma tabla al mismo tiempo.
-
Excluye filas que ya están en la tabla con
WHERE NOT EXISTS ...
o cualquier otra técnica aplicable: -
Seleccionar filas que no están presentes en otra tabla
-
Y no olvide eliminar los duplicados dentro el conjunto insertado también, que no ser excluido por el semi-anti-join
WHERE NOT EXISTS ...
Una técnica para tratar con ambos a la vez sería EXCEPT
:
INSERT INTO tbl (col1, col2)
VALUES
(text 'v1', text 'v2') -- explicit type cast may be needed in 1st row
, ('v3', 'v4')
, ('v3', 'v4') -- beware of dupes in source
EXCEPT SELECT col1, col2 FROM tbl;
EXCEPT
sin la palabra clave ALL
pliega las filas duplicadas en el origen. Si sabe que no hay duplicados, o no desea retirar los duplicados en silencio, use EXCEPT ALL
(o una de las otras técnicas). Ver:
- Uso de la cláusula EXCEPT en PostgreSQL
Generalmente, si la tabla de destino es grande , WHERE NOT EXISTS
en combinación con DISTINCT
en la fuente probablemente será más rápido:
INSERT INTO tbl (col1, col2)
SELECT *
FROM (
SELECT DISTINCT *
FROM (
VALUES
(text 'v1', text'v2')
, ('v3', 'v4')
, ('v3', 'v4') -- dupes in source
) t(c1, c2)
) t
WHERE NOT EXISTS (
SELECT FROM tbl
WHERE col1 = t.c1 AND col2 = t.c2
);
Si puede haber muchos duplicados, vale la pena doblarlos primero en la fuente. De lo contrario, use una subconsulta menos.
Relacionado:
- Seleccionar filas que no están presentes en otra tabla
Con escrituras simultáneas
Utilice Postgres UPSERT
implementación INSERT ... ON CONFLICT ...
en Postgres 9.5 o posterior:
INSERT INTO tbl (col1,col2)
SELECT DISTINCT * -- still can't insert the same row more than once
FROM (
VALUES
(text 'v1', text 'v2')
, ('v3','v4')
, ('v3','v4') -- you still need to fold dupes in source!
) t(c1, c2)
ON CONFLICT DO NOTHING; -- ignores rows with *any* conflict!
Lectura adicional:
- ¿Cómo usar RETURNING con ON CONFLICT en PostgreSQL?
- ¿Cómo inserto una fila que contiene una clave externa?
Documentación:
- El manual
- La página de confirmación
- La página wiki de Postgres
Respuesta de referencia de Craig para UPSERT
problemas:
- ¿Cómo UPSERT (COMBINAR, INSERTAR... EN ACTUALIZACIÓN DUPLICADA) en PostgreSQL?