MySQL массовая вставка или обновление - PullRequest
27 голосов
/ 09 июня 2011

Есть ли какой-нибудь способ выполнить массовый запрос типа INSERT OR UPDATE на сервере MySQL?

INSERT IGNORE ...

не будет работать, потому что, если поле уже существует, оно просто игнорирует его, а невставить что-нибудь.

REPLACE ...

не будет работать, потому что, если поле уже существует, оно сначала DELETE оно, а затем INSERT оно снова, а не обновляет его.

INSERT ... ON DUPLICATE KEY UPDATE

будет работать, но не может использоваться в массовом порядке.

Поэтому я хотел бы знать, есть ли какая-либо команда, подобная INSERT ... ON DUPLICATE KEY UPDATE, которая может быть выполнена массово (более одной строки вв то же время).

Ответы [ 5 ]

69 голосов
/ 10 августа 2011

Вы можете вставить / обновить несколько строк, используя INSERT ... ON DUPLICATE KEY UPDATE. Документация имеет следующий пример:

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

Или я неправильно понимаю ваш вопрос?

18 голосов
/ 09 июня 2011

Один из возможных способов сделать это - создать временную таблицу, вставить в нее данные, а затем выполнить 1 запрос с объединением, чтобы вставить несуществующие записи, а затем обновить их до существующих полей.Основы будут примерно такими:

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

Синтаксис может быть не точным, но это должно дать вам основы.Кроме того, я знаю, что это не красиво, но оно выполняет свою работу.

Обновление

Я поменял порядок вставки и обновления, потому что выполнение вставки сначала вызывает всевставленные строки будут обновлены при вызове обновления.Если вы сначала обновите, обновятся только существующие записи.Это должно означать немного меньше работы для сервера, хотя результаты должны быть одинаковыми.

2 голосов
/ 11 февраля 2014

Хотя на этот вопрос уже был дан правильный ответ (что MySQL поддерживает это с помощью ON DUPLICATE UPDATE с ожидаемым синтаксисом множества значений), я хотел бы подробнее остановиться на этом, предоставив демонстрацию того, что любой человек с MySQL может работать:

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;

Вывод следующий:

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)
0 голосов
/ 09 июня 2011

Если вы используете Oracle или Microsoft SQL, вы можете использовать MERGE. Однако MySQL не имеет прямой связи с этим утверждением. Вы упомянули решение с одной строкой, но, как вы отметили, оно не очень хорошо работает. Вот запись в блоге, которую я нашел о разнице между Oracle и MySQL и о том, как делать то, что Oracle делает с MERGE в MySQL:

http://blog.mclaughlinsoftware.com/2009/05/25/mysql-merge-gone-awry/

Это не очень хорошее решение, и, возможно, оно не такое полное, как хотелось бы, но я считаю, что это лучшее, что есть для решения.

0 голосов
/ 09 июня 2011

Попробуйте добавить триггер вставки, который выполняет предполетную проверку и отменяет вставку при дублировании ключа (после обновления существующей строки).

Не уверен, что он будет хорошо масштабироваться для массовых вставок, не говоря уже о работедля загрузки данных infile, но это лучшее, что я могу придумать.: -)

...