有没有一种方法可以使用ON DUPLICATE KEY更新所有我想插入的内容?


Answers:


103

不幸的是没有。

您可以不必重复该值而达到一半:

INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);

但是您仍然必须列出这些列。


@Neal:您要插入的值很复杂,我接受吗?
Lightness Races in Orbit

@Neal:取消分号。这都是一个查询。
Lightness Races in Orbit

哈哈谢谢^ _ ^。没注意到我已经把它留在那里了。现在尝试。
Naftali又名Neal

3
@Sohaib :UPDATE a = VALUES(a)+a, b = VALUES(b)+b, c = VALUES(c)+c

2
)使用价值的(指新的行和列与MySQL 8.0.20已过时开始,并受到在将来的去除dev.mysql.com/doc/refman/8.0/en/...
BhendiGawaar

41

采用 REPLACE INTO

的含义REPLACE INTO是,如果新记录提供了新的键值,则它将作为新记录插入。

如果新记录具有与预先存在的记录匹配的键值,则将忽略键冲突,新记录将替换先前存在的记录。


5
啊,那可能更好。值得一提的是,所有未在查询中明确给出的字段都将被默认设置,这显然与ON DUPLICATE KEY UPDATE行为有所不同。
Lightness Races in Orbit

67
注意:使用REPLACE,如果记录的键与已经存在的键匹配,则将删除旧行,并插入新行。如果您弄乱了触发器或外键约束,这可能是一件大事。
cHao 2012年

3
好点子。我猜,您冒着一些重大的连锁反应的风险。
Lightness Races in Orbit

1
还要注意mysqli_insert_id()不起作用!“如果最后一个查询不是INSERT或UPDATE语句,或者如果修改后的表没有具有AUTO_INCREMENT属性的列,则此函数将返回零。”
爱德华

要详细说明cHao的评论,这意味着您的新条目将具有与旧的“已替换”条目不同的自动增量ID。如果您在某个链接表上使用无法替换的链接表,这可能会很糟糕
Abraham Brookes

15

如果有用,我进行了一个查询以避免对版本> = 5.0的手写“重复”查询的最后一部分:

SELECT GROUP_CONCAT( CONCAT(COLUMN_NAME,"=values(", COLUMN_NAME,")") SEPARATOR ", ") FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'database_name' AND TABLE_NAME = 'table_name';

其输出是这样的:

a=values(a), b=values(b), c=values(c), d=values(d)

在具有a,b,c和d列的表上,因此您可以追加到查询的第一部分:

INSERT INTO `tableName` (`a`,`b`,`c`, `d`) VALUES (1,2,3,4) ON DUPLICATE KEY UPDATE a=values(a), b=values(b), c=values(c), d=values(d)

更新: 对于很长的列列表,您可能会看到截断的输出,可以在上面的查询之前使用此语句(感谢iroh叔叔):

SET SESSION group_concat_max_len = 1000000;

2
喜欢这个。有时,在您非常有帮助的查询之前,我需要这样做。SET SESSION group_concat_max_len = 1000000;
Iroh叔叔

1
你太棒了!
Damilola Olowookere

1

根据@BhendiGawaar对Orbit答案中的@Lightness Races的评论,这是MySQL 8.019+版本:

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

要么

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p)
  ON DUPLICATE KEY UPDATE c = m+n;

工程与set还有:

INSERT INTO t1 SET a=1,b=2,c=3 AS new
  ON DUPLICATE KEY UPDATE c = new.a+new.b;

INSERT INTO t1 SET a=1,b=2,c=3 AS new(m,n,p)
  ON DUPLICATE KEY UPDATE c = m+n;

直接从MySQL Docs复制

关于以下用途的弃用警告VALUES

从MySQL 8.0.20开始,不建议使用VALUES()来引用新的行和列,并且在将来的MySQL版本中会删除该值。而是使用行和列别名,如本节接下来的几节所述。


0

我知道这是一个老问题,这是一个有点非常规的答案,但是我遇到了同样的事情,并且在设置另一个答案中提到的group_concat_max_len属性时遇到了问题,并且总是得到截断的结果。编写长脚本时,我最终选择的另一个选择是在excel中使用以下公式:

=SUBSTITUTE(TRIM(A1), ",", "") & " = VALUES(" & SUBSTITUTE(TRIM(A1), ",", "") & "),"

其中A1是您将字段名称复制到的单元格。为了快速执行此操作,我将右键单击表,然后将select语句复制到剪贴板,该剪贴板将为您提供所有列名称,该公式将逗号删除。

希望这对某人有帮助!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.