Mysql SQL在使用重复密钥更新时插入多条记录

Mysql SQL在使用重复密钥更新时插入多条记录,mysql,sql,sql-insert,Mysql,Sql,Sql Insert,我有一个查询,它作为一个查询一次性插入多个数据 INSERT INTO tableName (COLUMN_1, COLUMN_2, COLUMN_3) SELECT 'test1', 'test2', 'test3' UNION ALL SELECT 'test4', 'test5', 'test6' UNION ALL SELECT 'test7', 'test8', 'test8' 使用上述代码,是否有一种方法实现“重复密钥更新”? 比如: INSERT INTO tableName

我有一个查询,它作为一个查询一次性插入多个数据

INSERT INTO tableName (COLUMN_1, COLUMN_2, COLUMN_3) 
SELECT 'test1', 'test2', 'test3'
UNION ALL
SELECT 'test4', 'test5', 'test6'
UNION ALL
SELECT 'test7', 'test8', 'test8'
使用上述代码,是否有一种方法实现“重复密钥更新”? 比如:

INSERT INTO tableName (COLUMN_1, COLUMN_2, COLUMN_3)
SELECT 'test1', 'test2', 'test3'
ON DUPLICATE KEY UPDATE COLUMN_1='new', COLUMN_2='new', COLUMN_3='new'
UNION ALL
SELECT 'test1', 'test2', 'test3'
ON DUPLICATE KEY UPDATE COLUMN_1='new', COLUMN_2='new', COLUMN_3='new'
UNION ALL
SELECT 'test1', 'test2', 'test3'
ON DUPLICATE KEY UPDATE COLUMN_1='new', COLUMN_2='new', COLUMN_3='new';

注意:可能与此无关或毫无意义,但我正在使用mysql workbench执行此操作。

您可以这样做:

INSERT INTO tableName (COLUMN_1, COLUMN_2, COLUMN_3)
SELECT * FROM (
    SELECT 'test1', 'test2', 'test3'
    UNION ALL
    SELECT 'test4', 'test5', 'test6'
    UNION ALL
    SELECT 'test7', 'test8', 'test8') AS derived_table
ON DUPLICATE KEY UPDATE COLUMN_1='new', COLUMN_2='new', COLUMN_3='new'
说明:

  • 您需要将
    SELECT
    和INSERT语句分开。也就是说,一个
    INSERT
    只能有一个
    SELECT
    。然后,您可以在select中执行UNION-s
  • 如上所述,
    插入到。。。选择。。。UNION不支持重复密钥更新时的
    -s。但是,它们在派生表(也称为子查询)上支持它

您尚未指定您拥有的主键和唯一索引,但这将起作用-提到了这种情况。根据找到行时的唯一约束,将更新所有三个列值(即使它们不是唯一键的一部分)


为了测试这一点,最好包含一些额外的行,因为示例数据中的每个值都是唯一的,并且您无法观察其行为。

您的查询基本上是正确的,只需去掉重复键上的中间值…
。不需要派生表,因为您没有引用联合中的列

INSERT INTO tableName (COLUMN_1, COLUMN_2, COLUMN_3) 
SELECT 'test8', 'test9', 'test10'
UNION ALL
SELECT 'test4', 'test5', 'test6'
UNION ALL
SELECT 'test9', 'test5', 'test6'
ON DUPLICATE KEY UPDATE COLUMN_1='new', COLUMN_2='new', COLUMN_3='new';
您将遇到的问题是,如果在
INSERT
上获得多个重复键。在这种情况下,
UPDATE
将尝试将两行设置为具有相同的键(“new”),而
INSERT
将失败。您可以通过更改查询来解决此问题,以便
UPDATE
包含旧列值的一部分。在这种情况下,由于要引用列值,因此需要一个派生表:

INSERT INTO tableName (COLUMN_1, COLUMN_2, COLUMN_3) 
SELECT * FROM (
    SELECT 'test8', 'test9', 'test10'
    UNION ALL
    SELECT 'test4', 'test5', 'test6'
    UNION ALL
    SELECT 'test1', 'test5', 'test6') AS dt
ON DUPLICATE KEY UPDATE COLUMN_1=CONCAT('new', COLUMN_1), COLUMN_2='new', COLUMN_3='new';

您的第一个插入查询无效。不能合并所有INSERT语句。@KamilG.-对不起,我弄错了。我如何编辑这个问题来解决它?点击你帖子标签下面的灰色编辑按钮。你的桌子上有什么键?当values子句看起来更合适时,为什么要使用select?@KamilG。编辑。请参阅更新的问题问:如果第一个是重复的,那么第二个是重复的,或者第三个是重复的,等等,会发生什么。?它们现在是否都有类似的记录?是和否。这将导致一个错误,因为它们将以相同的键值(“new”)结束,并且不会发生插入。因此,如果从同一个
INSERT
中获得两个或多个重复的键,则尝试使用常量值进行更新是不可行的。那么这是否意味着,这是不可取的?我在想,对于每一次插入,都会有一个重复的密钥更新,它将指定如果记录是重复的,记录将是什么。必须在最后设置它(复制密钥更新)可能会导致一个问题,这可能会导致尽可能多的问题,即使要捕获它,我也会尽量避免(通过try-catch)。你知道我还能怎么做吗?谢谢你的更新!抱歉,我似乎不明白您在最后两条语句中的意思:“您可以通过更改查询来解决此问题,以便更新包含旧列值的一部分。在这种情况下,由于您将引用列值,因此需要一个派生表”。你能解释一下吗?如果你看我的新查询,你会看到
列1上的
更新
现在使用部分旧值来创建新值。如果插入的数据中有一个以上的键与表中已有的键相匹配,这将有助于防止重复的键错误。由于此
更新
现在指的是
联合
中的一列,规则(如其他答案提供的链接中所指出的)意味着您必须使用派生表(因此我们使用
SELECT*FROM(SELECT…UNION…UNION…)作为dt
)问题:如果第一个表是重复的,那么第二个表也是重复的,会发生什么,还是第三个,等等。?他们现在会有相似的记录吗?问题:如果第一个是重复的,那么第二个,或者第三个,等等,会发生什么。?他们现在会有相似的记录吗?回答:你为什么不自己试试呢?这是最好的学习方法。设置起来很容易。我认为,由于后续更新的唯一约束冲突,它应该会引发一个错误。
INSERT INTO tableName (COLUMN_1, COLUMN_2, COLUMN_3) 
SELECT * FROM (
    SELECT 'test8', 'test9', 'test10'
    UNION ALL
    SELECT 'test4', 'test5', 'test6'
    UNION ALL
    SELECT 'test1', 'test5', 'test6') AS dt
ON DUPLICATE KEY UPDATE COLUMN_1=CONCAT('new', COLUMN_1), COLUMN_2='new', COLUMN_3='new';