SQL proporciona diferentes formas de actualizar o insertar datos en una tabla:
Cuándo y qué utilizar:
INSERT.UPDATE con condiciones.MERGE o UPSERT — esto ahorra complejidad y reduce la cantidad de consultas SQL.Ejemplo (PostgreSQL):
INSERT INTO employees(id, name, salary) VALUES (1, 'Ivan', 100000) ON CONFLICT (id) DO UPDATE SET salary = EXCLUDED.salary;
Impacto en el rendimiento y la integridad:
¿Qué sucederá si se intenta realizar un UPSERT en un campo único, pero al mismo tiempo se inserta y actualiza la misma fila en la misma transacción?
Respuesta correcta: Puede ocurrir un error de bloqueo/conflicto, ya que la transacción intentará modificar la misma fila dos veces. La operación no se completará o finalizará con un error deadlock dependiendo del SGBD.
Ejemplo:
BEGIN; INSERT INTO users(id, name) VALUES (1, 'Oleg') ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name; UPDATE users SET name = 'Petr' WHERE id = 1; COMMIT;
Con un orden y nivel de aislamiento incorrectos, puede haber un conflicto de cambios.
Historia #1
En una lógica de migración de datos, se utilizó una combinación de SELECT y luego INSERT o UPDATE, lo que a veces provocaba que otra transacción estableciera los datos antes, y ocurría un error de "clave duplicada". Esto provocó frecuentes fallos en la exportación nocturna de datos, fue necesario reemplazar la lógica por UPSERT.
Historia #2
En un proyecto en MySQL se utilizó incorrectamente ON DUPLICATE KEY UPDATE, que no consideraba correctamente las claves únicas compuestas. Como resultado, parte de los datos no se actualizaba y aparecían duplicados. El problema solo se pudo identificar en el entorno de producción.
Historia #3
En un proyecto se utilizó UPDATE en lugar de UPSERT para la sincronización de datos del usuario. En caso de fallos de conexión, se perdía parte de los datos, ya que se omitía la actualización para nuevos usuarios. Después de un análisis, se implementó completamente MERGE/UPSERT.