Mysql 有没有一种方法可以使用复制密钥来更新我想要插入的所有内容?

Mysql 有没有一种方法可以使用复制密钥来更新我想要插入的所有内容?,mysql,insert,on-duplicate-key,Mysql,Insert,On Duplicate Key,我知道,如果已经有某个密钥的记录,您可以使用重复密钥更新上的来更新某个值 我可以这样做: INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE `a`=1, `b`=2, `c`=3 但是,我如何做到这一点而不必写两次列和值呢? 不必重复该值,就可以达到一半: INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3) ON DUPLICAT

我知道,如果已经有某个密钥的记录,您可以使用重复密钥更新上的
来更新某个值

我可以这样做:

INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1, 2, 3)
ON DUPLICATE KEY UPDATE `a`=1, `b`=2, `c`=3
但是,我如何做到这一点而不必写两次列和值呢?

不必重复该值,就可以达到一半:

INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
但是您仍然必须列出列。

使用

REPLACE INTO
的意思是,如果新记录显示新的键值,那么它将作为新记录插入


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

如果有用,我提出了一个查询,以避免手动写入“重复”查询的最后一部分,对于版本>=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)
更新: 对于很长的列列表,您可能会看到截断的输出,您可以在上面的查询之前使用此语句(谢谢):


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

=SUBSTITUTE(TRIM(A1), ",", "") & " = VALUES(" & SUBSTITUTE(TRIM(A1), ",", "") & "),"
其中A1是将字段名复制到的单元格。为了快速完成这项工作,我右键单击该表并将select语句复制到剪贴板,它将为您提供所有列名称,公式将删除逗号


希望这对别人有帮助

根据@BhendiGawaar对@Lightness Races in Orbit答案的评论,以下是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;

也可与
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 8.0.20开始,不推荐使用VALUES()来引用新行和新列,在MySQL的未来版本中可能会删除它。相反,请使用行别名和列别名,如本节后面几段所述


@尼尔:你要插入的值很复杂,我想是吧?@Neal:去掉分号。这都是一个问题。哈哈,谢谢。没有注意到我把它落在那里了。现在试一试。@Sohaib:
更新a=VALUES(a)+a,b=VALUES(b)+b,c=VALUES(c)+c
?从MySQL 8.0.20开始,使用VALUES()来引用新行和新列是不推荐的,将来可能会被删除啊,这可能会更好。值得注意的是,查询中未明确给出的所有字段都将默认,这显然不同于重复键更新时的
行为。注意:使用
REPLACE
,如果记录的键与已经存在的某个匹配,则将删除旧行,并插入新行。如果你弄乱了触发器或外键约束,这可能是一件大事。这一点很好。我想,您可能会面临一些严重的连锁反应。还要注意,mysqli_insert_id()不起作用!“如果最后一个查询不是INSERT或UPDATE语句,或者如果修改的表没有具有AUTO_INCREMENT属性的列,则此函数将返回零。”要详细说明赵的注释,这意味着您的新条目将具有不同于旧“替换”条目的自动增量ID。如果您在某个地方使用的链接表无法捕获替换项,那么这可能会非常糟糕。有时候,在你提出非常有用的问题之前,我需要这个。设置会话组\u concat\u max\u len=1000000;
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;
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;