我知道,ON DUPLICATE KEY UPDATE
如果已经有该键的记录,则可以用来更新某个值,
我可以做这个:
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1, 2, 3)
ON DUPLICATE KEY UPDATE `a`=1, `b`=2, `c`=3
但是,如何不必写两次列和值就可以做到这一点呢?
Answers:
您可以不必重复该值而达到一半:
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
但是您仍然必须列出这些列。
UPDATE a = VALUES(a)+a, b = VALUES(b)+b, c = VALUES(c)+c
?
采用 REPLACE INTO
的含义REPLACE INTO
是,如果新记录提供了新的键值,则它将作为新记录插入。
如果新记录具有与预先存在的记录匹配的键值,则将忽略键冲突,新记录将替换先前存在的记录。
ON DUPLICATE KEY UPDATE
行为有所不同。
REPLACE
,如果记录的键与已经存在的键匹配,则将删除旧行,并插入新行。如果您弄乱了触发器或外键约束,这可能是一件大事。
如果有用,我进行了一个查询以避免对版本> = 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;
根据@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版本中会删除该值。而是使用行和列别名,如本节接下来的几节所述。
我知道这是一个老问题,这是一个有点非常规的答案,但是我遇到了同样的事情,并且在设置另一个答案中提到的group_concat_max_len属性时遇到了问题,并且总是得到截断的结果。编写长脚本时,我最终选择的另一个选择是在excel中使用以下公式:
=SUBSTITUTE(TRIM(A1), ",", "") & " = VALUES(" & SUBSTITUTE(TRIM(A1), ",", "") & "),"
其中A1是您将字段名称复制到的单元格。为了快速执行此操作,我将右键单击表,然后将select语句复制到剪贴板,该剪贴板将为您提供所有列名称,该公式将逗号删除。
希望这对某人有帮助!