MySQL批量INSERT或UPDATE

时间:2011-06-08 23:24:23

标签: mysql sql bulk

有没有办法在MySQL服务器上批量执行INSERT OR UPDATE之类的查询?

INSERT IGNORE ...

不起作用,因为如果该字段已经存在,它将简单地忽略它而不插入任何内容。

REPLACE ...

无法使用,因为如果该字段已经存在,它将首先DELETE,然后再INSERT,而不是更新它。

INSERT ... ON DUPLICATE KEY UPDATE

可以使用,但不能批量使用。

所以我想知道是否有像INSERT ... ON DUPLICATE KEY UPDATE这样的命令可以批量发布(同时多行)。

5 个答案:

答案 0 :(得分:68)

可以使用INSERT ... ON DUPLICATE KEY UPDATE插入/更新多行。 documentation有以下示例:

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

或者我误解了你的问题?

答案 1 :(得分:18)

执行此操作的一种可能方法是创建临时表,将数据插入到该表中,然后使用连接执行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

语法可能不准确,但这应该为您提供基础知识。此外,我知道它不漂亮,但它完成了工作。

<强>更新

我交换了插入和更新的顺序,因为首先执行insert会导致在调用更新时更新所有插入的行。如果首先更新,则仅更新现有记录。这应该对服务器的工作少一点,尽管结果应该是相同的。

答案 2 :(得分:2)

虽然这个问题已经得到了正确回答(MySQL确实通过ON DUPLICATE UPDATE使用预期的多值集语法来支持这个问题),但我想通过提供任何MySQL运行的演示来扩展它:< / p>

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)

答案 3 :(得分:0)

尝试添加执行飞行前检查的插入触发器,并取消重复键上的插入(在更新现有行之后)。

不确定它是否适合批量插入,更不用说加载数据了,但这是我能想到的最好的。 : - )

答案 4 :(得分:0)

如果您使用的是Oracle或Microsoft SQL,则可以使用MERGE。但是,MySQL与该语句没有直接关联。您提到的是单行解决方案,但正如您所指出的那样,它不会很好地进行批量处理。这是一篇关于Oracle和MySQL之间差异的博客文章,以及Oracle如何在MySQL中使用MERGE做的事情:

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

这不是一个漂亮的解决方案,它可能不是你想要的完整解决方案,但我相信这是最好的解决方案。