los - trigger para insertar mysql
MySQL a granel INSERTAR o ACTUALIZAR (5)
¿Hay alguna forma de realizar una consulta masiva como INSERT OR UPDATE
en el servidor MySQL?
INSERT IGNORE ...
no funcionará, porque si el campo ya existe, simplemente lo ignorará y no insertará nada.
REPLACE ...
no funcionará, porque si el campo ya existe, primero lo DELETE
y luego lo INSERT
nuevamente, en lugar de actualizarlo.
INSERT ... ON DUPLICATE KEY UPDATE
Funcionará, pero no se puede utilizar a granel.
Así que me gustaría saber si hay algún comando como INSERT ... ON DUPLICATE KEY UPDATE
que pueda emitirse de forma masiva (más de una fila al mismo tiempo).
Aunque esta pregunta ya ha sido respondida correctamente (que MySQL sí lo admite a través de ON DUPLICATE UPDATE con la sintaxis de conjunto de valores múltiples esperados), me gustaría expandir esto proporcionando una demostración que cualquier persona con MySQL puede ejecutar:
CREATE SCHEMA IF NOT EXISTS `test`;
DROP TABLE IF EXISTS test.new_table;
CREATE TABLE test.new_table (`Key` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`Key`)) ENGINE=InnoDB AUTO_INCREMENT=106 DEFAULT CHARSET=utf8;
SELECT * FROM test.new_table;
INSERT INTO test.new_table VALUES (1),(2),(3),(4),(5) ON DUPLICATE KEY UPDATE `Key`=`Key`+100;
SELECT * FROM test.new_table;
INSERT INTO test.new_table VALUES (1),(2),(3),(4),(5) ON DUPLICATE KEY UPDATE `Key`=`Key`+100;
SELECT * FROM test.new_table;
La salida es la siguiente:
Empty set (0.00 sec)
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
+-----+
| Key |
+-----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+-----+
5 rows in set (0.00 sec)
Query OK, 10 rows affected (0.00 sec)
Records: 5 Duplicates: 5 Warnings: 0
+-----+
| Key |
+-----+
| 101 |
| 102 |
| 103 |
| 104 |
| 105 |
+-----+
5 rows in set (0.00 sec)
Intente agregar un activador de inserción que realice una comprobación previa al vuelo y cancele la inserción en clave duplicada (después de actualizar la fila existente).
No estoy seguro de que se pueda escalar bien para inserciones masivas, y mucho menos trabajar para el archivo de datos de carga, pero es lo mejor que puedo imaginar :-)
Puede insertar / actualizar varias filas usando INSERTAR ... EN ACTUALIZACIÓN DE LA TECLA DUPLICADA. La documentation tiene el siguiente ejemplo:
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
¿O estoy malinterpretando tu pregunta?
Si estaba usando Oracle o Microsoft SQL, podría usar el MERGE
. Sin embargo, MySQL no tiene una correlación directa con esa declaración. Existe la solución de una sola fila que mencionó pero, como usted señaló, no funciona muy bien. Aquí hay una publicación de blog que encontré sobre la diferencia entre Oracle y MySQL y cómo hacer lo que Oracle hace con MERGE
en MySQL:
http://blog.mclaughlinsoftware.com/2009/05/25/mysql-merge-gone-awry/
No es una solución bonita y probablemente no sea una solución tan completa como le gustaría, pero creo que es la mejor solución para una solución.
Una forma posible de hacer esto es crear una tabla temporal, insertar los datos en ella y luego hacer una consulta con una combinación para insertar los registros que no existen seguidos por y actualizar a los campos que existen. Lo básico sería algo como esto.
CREATE TABLE MyTable_Temp LIKE MyTable
LOAD DATA INFILE..... INTO MyTable_Temp
UPDATE MyTable INNER JOIN
MyTable_Temp
ON MyTable.ID=MyTable_Temp.ID
SET MyTable.Col1=MyTable_Temp.Col1, MyTable.Col2=MyTable_Temp.Col2.....
INSERT INTO MyTable(ID,Col1,Col2,...)
SELECT ID,Col1,Col2,...
FROM MyTable_Temp
LEFT JOIN MyTable
ON MyTable_Temp.ID = MyTable.ID
WHERE myTable.ID IS NULL
DROP TABLE MyTable_Temp
La sintaxis puede no ser exacta, pero esto debería darle los conceptos básicos. Además, sé que no es bonito, pero hace el trabajo.
Actualizar
Cambié el orden de inserción y actualización, ya que al hacer la inserción primero se actualizan todas las filas insertadas cuando se llama a la actualización. Si actualiza primero, solo se actualizan los registros existentes. Esto debería significar un poco menos de trabajo para el servidor, aunque los resultados deberían ser los mismos.