on duplicate key update用法 和replace区别

MySQL插入更新技巧
本文介绍MySQL中使用INSERT...ON DUPLICATE KEY UPDATE语句处理数据插入和更新的方法,以及与REPLACE语句的区别。通过具体实例解释如何在多行记录插入时有效利用VALUES函数解决更新问题。

[转载于]https://blog.youkuaiyun.com/jaryle/article/details/75909531

【强调】注意:where条件跟的字段必须唯一(主键也唯一)

insert语句的末尾添加on duplicate key update语法:如果插入行出现唯一索引或者主键重复时,则执行旧的update;如果不会导致唯一索引或者主键重复时,就直接添加新行。

例如:如果列a被定义成唯一索引(unique)或者主键(primary key),并且a=1,此时使用insert 语句的末尾加on duplicate key update语句时,

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

UPDATE TABLE SET c=c+1 WHERE a=1; 

这二个语句的执行效果是一样的。此时a=1并且是唯一索引或者主键,上面的语句就会出现唯一索引或者主键重复,此时on duplicate key update就在原有数据上更新c=c+1新的数据b没有被插入进去,只是更新了c的值。

扩展知识一:

现在问题来了,如果INSERT多行记录, ON DUPLICATE KEY UPDATE后面字段的值怎么指定?要知道一条INSERT语句中只能有一个ON DUPLICATE KEY UPDATE,到底他会更新一行记录,还是更新所有需要更新的行。这个问题困扰了我很久了,其实使用VALUES()函数一切问题都解决了。

举个例子,字段a被定义为UNIQUE,并且原数据库表table中已存在记录(2,2,9)和(3,2,1),如果插入记录的a值与原有记录重复,则更新原有记录,否则插入新行:

INSERT INTO TABLE (a,b,c) VALUES 
(1,2,3), 
(2,5,7), 
(3,3,6), 
(4,8,2) 
ON DUPLICATE KEY UPDATE b=VALUES(b); 

以上sql语句,发现(4,5,6)和已存在记录(2,2,9)发生唯一值冲突,此时就执行update b=VALUES(b),执行后的结果将原有记录(2,2,9)更新为(2,5,9),将(3,2,1)更新成(3,3,1),插入新记录(1,2,3)和(4,8,2) 

扩展知识二:

mysql之replace和ON DUPLICATE KEY UPDATE的区别

(1)在没有主键或者唯一索引重复时,replace与insert .. on deplicate udpate相同。

(2)在主键或者唯一索引重复时,replace是delete老记录,而录入新的记录,所以原有的所有记录会被清除,这个时候,如果replace语句的字段不全的话,有些原有的比如c字段的值会被自动填充为默认值。而insert .. duplicate update则只执行update标记之后的sql,从表象上来看相当于一个简单的update语句。它保留了所有字段的旧值,只更新update后面的语句,而replace没有保留旧值,直接删除再insert新值。
从底层执行效率上来讲,replace要比insert .. on duplicate update效率要高,但是在写replace的时候,字段要写全,防止老的字段数据被删除。

在 TiDB 中,`INSERT ... ON DUPLICATE KEY UPDATE` `REPLACE` 是两种常见的用于处理数据插入更新的语句。尽管它们的功能类似,但在实现机制、锁行为性能方面存在显著差异。 ### 实现机制 - **INSERT ... ON DUPLICATE KEY UPDATE**:当插入的数据导致唯一键(包括主键)冲突时,会执行指定的更新操作。这种机制允许对现有记录进行部分更新,而不会删除重新插入整行。 - **REPLACE**:当插入的数据导致唯一键冲突时,TiDB 会先删除冲突的旧记录,然后尝试重新插入新记录。这意味着如果存在多个唯一索引,可能会触发多次删除插入操作。 ### 锁行为 - **INSERT ... ON DUPLICATE KEY UPDATE**:在检测到唯一键冲突时,会对相关行加锁以确保事务的隔离性一致性。由于只是更新现有行,锁定的范围通常较小。 - **REPLACE**:由于需要先删除冲突的记录再插入新记录,因此涉及更多的锁操作。删除操作会导致对相关行的独占锁,插入操作同样需要获取相应的锁。这可能导致更高的锁竞争更长的等待时间。 ### 性能差异 1. **写入吞吐量**: - `INSERT ... ON DUPLICATE KEY UPDATE` 通常具有更高的写入吞吐量,因为它避免了删除重新插入整行的操作。更新操作仅修改受影响的列,减少了 I/O 操作日志写入量。 - `REPLACE` 的性能相对较低,因为每次操作都可能涉及两次写入(删除插入),增加了数据库的负担 [^1]。 2. **事务开销**: - `INSERT ... ON DUPLICATE KEY UPDATE` 在事务中只需要一次提交即可完成插入或更新操作,减少了事务的开销。 - `REPLACE` 需要两次独立的操作(删除插入),每个操作都需要单独的日志记录事务管理,增加了事务的复杂性开销 [^2]。 3. **索引维护**: - `INSERT ... ON DUPLICATE KEY UPDATE` 只需更新受影响的索引条目,减少了索引重建的成本。 - `REPLACE` 需要先删除旧记录,导致所有相关的索引条目被标记为删除,然后再插入新记录时重新生成索引条目,增加了索引维护的开销 [^3]。 4. **并发控制**: - `INSERT ... ON DUPLICATE KEY UPDATE` 在高并发环境下表现更好,因为它对行的锁定范围较小,减少了锁竞争的可能性。 - `REPLACE` 由于涉及更多的锁操作,容易引发死锁或阻塞其他事务,尤其是在大量并发写入的情况下 [^4]。 ### 使用建议 - 如果只需要对现有记录的部分字段进行更新,推荐使用 `INSERT ... ON DUPLICATE KEY UPDATE`,因为它在性能资源消耗上更为高效。 - 如果确实需要完全替换某条记录(例如,删除旧记录并插入新记录),可以考虑使用 `REPLACE`,但需要注意其带来的额外开销潜在的锁竞争问题。 ```sql -- 示例:INSERT ... ON DUPLICATE KEY UPDATE INSERT INTO users (id, name, email) VALUES (1, 'Alice', 'alice@example.com') ON DUPLICATE KEY UPDATE name = 'Alice', email = 'alice@example.com'; -- 示例:REPLACE REPLACE INTO users (id, name, email) VALUES (1, 'Alice', 'alice@example.com'); ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值