mysql-on duplicate key update实现insertOrUpdate官方文档
Posted PacosonSWJTU
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql-on duplicate key update实现insertOrUpdate官方文档相关的知识,希望对你有一定的参考价值。
【README】
mysql 基于 on duplicate key update filed=value ; 实现有则更新,没有则插入;
以下内容总结于 https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
【1】api 描述
如果指定 ON DUPLICATE KEY UPDATE 子句并且要插入的行会导致 UNIQUE 索引或 PRIMARY KEY 中出现重复值,则会发生旧行的 UPDATE。 例如,如果列 a 声明为 UNIQUE 并包含值 1,则以下两个语句具有类似的效果:
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE t1 SET c=c+1 WHERE a=1;
效果并不完全相同:对于 a 是自增列的 InnoDB 表,INSERT 语句增加自增值,但 UPDATE 不会。如果列 b 也是唯一的,则 INSERT 等效于此 UPDATE 语句:
UPDATE t1 SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
也就说, 表t1 要有唯一键,才能保证实现新增或更新的效果; 因为主键肯定不一样;
注意:如果 a=1 OR b=2 匹配多行,则只更新一行。 通常,您应该尽量避免在具有多个唯一索引的表上使用 ON DUPLICATE KEY UPDATE 子句。
【1.1】更新行数
使用 ON DUPLICATE KEY UPDATE,如果将行作为新行插入,则每行的受影响行值为 1,如果更新现有行,则为 2,如果现有行设置为其当前值,则为 0。 如果在连接到 mysqld 时为 mysql_real_connect() C API 函数指定 CLIENT_FOUND_ROWS 标志,则如果现有行设置为其当前值,则受影响的行值为 1(而不是 0)。
【1.2】可以更新多个列
ON DUPLICATE KEY UPDATE 子句可以包含多个列分配,以逗号分隔。
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1, c2=2, c3=3;
【1.3】 values() 函数引用值
可以使用 VALUES(col_name) 函数来引用来自 INSERT ... ON DUPLICATE KEY UPDATE 语句的 INSERT 部分的列值。 换句话说,ON DUPLICATE KEY UPDATE 子句中的 VALUES(col_name) 是指将插入的 col_name 的值,没有发生重复键冲突。 此函数在多行插入中特别有用。 VALUES() 函数仅在 ON DUPLICATE KEY UPDATE 子句或 INSERT 语句中有意义,否则返回 NULL。 例子:
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
-- 等价于
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=3;
INSERT INTO t1 (a,b,c) VALUES (4,5,6)
ON DUPLICATE KEY UPDATE c=9;
注意: 从 MySQL 8.0.20 开始,不推荐使用 VALUES() 来引用新的行和列(可能会被删除),并且在未来的 MySQL 版本中可能会被删除。 相反,使用行和列别名,如本节接下来的几段所述。
【1.4】为行使用别名(mysql8.0.19才可以,注意版本)
从 MySQL 8.0.19 开始,可以为行使用别名,可以选择插入一个或多个列,在 VALUES 或 SET 子句之后,并以 AS 关键字开头。 使用行别名 new,前面显示的使用 VALUES() 访问新列值的语句可以写成如下所示的形式:
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;
补充: 从 MySQL 8.0.20 开始,在 UPDATE 子句中使用 VALUES() 的 INSERT ... SELECT ... ON DUPLICATE KEY UPDATE 语句会抛出警告:
INSERT INTO t1
SELECT c, c+d FROM t2
ON DUPLICATE KEY UPDATE b = VALUES(b);
-- 等价于
INSERT INTO t1
SELECT * FROM (SELECT c, c+d AS e FROM t2) AS dt
ON DUPLICATE KEY UPDATE b = e;
【1.5】将行和列别名与 SET 子句一起使用,而不用values
在刚刚显示的两个 INSERT ... ON DUPLICATE KEY UPDATE 语句中使用 SET 而不是 VALUES 可以如下所示完成:
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;
【1.6】行别名不能与表名相同。
如果未使用列别名,或者它们与列名相同,则必须使用 ON DUPLICATE KEY UPDATE 子句中的行别名来区分它们。 列别名对于它们所应用的行别名必须是唯一的(即,没有引用同一行列的列别名可能是相同的)。
【2】insert ... select ... on duplicate key update (不建议使用,不安全,参见文末)
对于 INSERT ... SELECT 语句,这些规则适用于可以在 ON DUPLICATE KEY UPDATE 子句中引用的可接受形式的 SELECT 查询表达式:
- 对来自单个表(可能是派生表)的查询的列的引用。
- 对多个表的连接查询中的列的引用。
- 对来自 DISTINCT 查询的列的引用。
- 引用其他表中的列,只要 SELECT 不使用 GROUP BY。 一个副作用是您必须限定对非唯一列名的引用。
【2.1】不支持从 UNION 引用列。
要解决此限制,请将 UNION 重写为派生表,以便可以将其行视为单表结果集。 例如,此语句会产生错误(语法错误):
INSERT INTO t1 (a, b)
SELECT c, d FROM t2
UNION
SELECT e, f FROM t3
ON DUPLICATE KEY UPDATE b = b + c;
相反,使用将 UNION 重写为派生表的等效语句(语法正确):
INSERT INTO t1 (a, b)
SELECT * FROM
(SELECT c, d FROM t2
UNION
SELECT e, f FROM t3) AS dt
ON DUPLICATE KEY UPDATE b = b + c;
【2.2】支持group by
将查询重写为派生表的技术还支持从 GROUP BY 查询引用列。
【2.3】INSERT ... SELECT ON DUPLICATE KEY UPDATE 语句是不安全的
因为 INSERT ... SELECT 语句的结果取决于来自 SELECT 的行的顺序,并且无法始终保证此顺序,所以在记录 INSERT ... SELECT ON DUPLICATE KEY UPDATE 语句时源和副本可能会出现分歧 . 因此,对于基于语句的复制,INSERT ... SELECT ON DUPLICATE KEY UPDATE 语句被标记为不安全(谨慎使用 insert ... select on duplicate key update )。
此类语句在使用基于语句的模式时会在错误日志中产生警告,并在使用 MIXED 模式时使用基于行的格式写入二进制日志。 针对具有多个唯一键或主键的表的 INSERT ... ON DUPLICATE KEY UPDATE 语句也被标记为不安全。 (错误#11765650,错误#58637)
以上是关于mysql-on duplicate key update实现insertOrUpdate官方文档的主要内容,如果未能解决你的问题,请参考以下文章
selenium 之 ActionChains (key_down,key_up,send_keys_to_element,send_keys)
qt 键盘事件Key_Left,Right,Up,Down事件捕捉不了,而A,S,D,W能捕捉,为啥啊