Algunos servidores SQL tienen una característica que INSERTse omite si viola una restricción de clave principal / única. Por ejemplo, MySQL tiene INSERT IGNORE.
¿Cuál es la mejor manera de emular INSERT IGNOREy ON DUPLICATE KEY UPDATEcon PostgreSQL?
database
postgresql
rules
gpilotino
fuente
fuente

ON DUPLICATE KEY UPDATEen PgSQL 9.5 todavía es algo imposible, porque elON CLAUSEequivalente de PgSQL requiere que proporcione el nombre de la restricción, mientras que MySQL podría capturar cualquier restricción sin la necesidad de definirlo. Esto me impide "emular" esta función sin tener que volver a escribir consultas.Respuestas:
Intenta hacer una ACTUALIZACIÓN. Si no modifica ninguna fila, eso significa que no existía, entonces haga una inserción. Obviamente, haces esto dentro de una transacción.
Por supuesto, puede envolver esto en una función si no desea poner el código adicional en el lado del cliente. También necesita un bucle para la rara condición de carrera en ese pensamiento.
Hay un ejemplo de esto en la documentación: http://www.postgresql.org/docs/9.3/static/plpgsql-control-structures.html , ejemplo 40-2 justo en la parte inferior.
Esa suele ser la forma más fácil. Puedes hacer algo de magia con las reglas, pero es probable que sea mucho más complicado. Recomendaría el enfoque de envoltura en función sobre eso cualquier día.
Esto funciona para una sola fila, o pocas filas, valores. Si está tratando con grandes cantidades de filas, por ejemplo, de una subconsulta, es mejor dividirla en dos consultas, una para INSERTAR y otra para ACTUALIZAR (como una unión / subselección apropiada, por supuesto, no es necesario escribir su principal filtrar dos veces)
fuente
INSERT ... ON CONFLICT DO NOTHING;. Consulte también la respuesta stackoverflow.com/a/34639631/2091700 .MERGEes un complemento seguro de concurrencia, a menos que tome una primera. La gente lo usa de esa manera, pero está mal.LOCK TABLECon PostgreSQL 9.5, esta es ahora una funcionalidad nativa (como MySQL ha tenido durante varios años):
...
fuente
Editar: en caso de que se haya perdido la respuesta de Warren, PG9.5 ahora tiene esto de forma nativa; hora de actualizar!
Sobre la base de la respuesta de Bill Karwin, para explicar cómo se vería un enfoque basado en reglas (transferencia desde otro esquema en el mismo DB y con una clave principal de varias columnas):
Nota: La regla se aplica a todas las
INSERToperaciones hasta que se descarta, por lo que no es muy ad hoc.fuente
another_schema.my_tablecontiene duplicados de acuerdo con las restricciones demy_table?INSERT INTO "my_table" SELECT DISTINCT ON (pk_col_1, pk_col_2) * FROM the_tmp_table;DELETE FROM my_table WHERE ctid IN (SELECT ctid FROM (SELECT ctid,ROW_NUMBER() OVER (PARTITION BY pk_col_1,pk_col_2) AS rn FROM my_table) AS dups WHERE dups.rn > 1);Para aquellos de ustedes que tienen Postgres 9.5 o superior, la nueva sintaxis ON CONFLICT DOH NOTHING debería funcionar:
Para aquellos de nosotros que tenemos una versión anterior, esta combinación correcta funcionará en su lugar:
fuente
Unique violation: 7 ERROR: duplicate key value violates unique constraintcuando setarget_tableinsertó otra fila mientras se ejecutaba esta consulta, si sus claves, de hecho, se duplican entre sí. Creo que el bloqueotarget_tableayudará, pero la concurrencia obviamente sufrirá.ON CONFLICT (field_one) DO NOTHINGEs la mejor parte de la respuesta.Para obtener la lógica de ignorar inserción , puede hacer algo como a continuación. Descubrí que simplemente insertar desde una instrucción select de valores literales funcionó mejor, luego puede enmascarar las claves duplicadas con una cláusula NOT EXISTS. Para obtener la actualización en lógica duplicada, sospecho que sería necesario un bucle pl / pgsql.
fuente
fuente
Parece que PostgreSQL admite un objeto de esquema llamado regla .
http://www.postgresql.org/docs/current/static/rules-update.html
Puede crear una regla
ON INSERTpara una tabla determinada, haciéndoloNOTHINGsi existe una fila con el valor de clave principal dado, o haciendo que haga una enUPDATElugar deINSERTsi existe una fila con el valor de clave principal dado.No lo he intentado yo mismo, así que no puedo hablar por experiencia ni ofrecer un ejemplo.
fuente
Como @hanmari mencionó en su comentario. cuando se inserta en tablas de postgres, el conflicto on (..) no hacer nada es el mejor código para no insertar datos duplicados .:
La línea de código ON CONFLICT permitirá que la instrucción de inserción aún inserte filas de datos. El código de consulta y valores es un ejemplo de fecha insertada desde un Excel en una tabla db de postgres. Tengo restricciones agregadas a una tabla de postgres que uso para asegurarme de que el campo ID sea único. En lugar de ejecutar una eliminación en filas de datos que son iguales, agrego una línea de código sql que renumera la columna ID a partir de 1. Ejemplo:
Si mis datos tienen un campo de ID, no lo uso como ID principal / ID en serie, creo una columna de ID y la configuro en serie. Espero que esta información sea útil para todos. * No tengo título universitario en desarrollo / codificación de software. Todo lo que sé en codificación, lo estudio por mi cuenta.
fuente
Esta solución evita el uso de reglas:
pero tiene un inconveniente de rendimiento (ver PostgreSQL.org ):
fuente
En forma masiva, siempre puede eliminar la fila antes de la inserción. La eliminación de una fila que no existe no causa un error, por lo que se omite de forma segura.
fuente
DEFERRABLE INITIALLY DEFERREDbanderas.Para los scripts de importación de datos, para reemplazar "SI NO EXISTE", en cierto modo, hay una formulación un poco incómoda que, sin embargo, funciona:
fuente