mysql-ON DUPLICATE KEY UPDATE

官方文档

sql语句:

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

表t1中,存在(a是唯一索引),则上述sql语句等同于

if(表中不存a=1的数据) :
   INSERT INTO t1 (a,b,c) VALUES (1,2,3)  
else  
   UPDATE t1 SET c=c+1 WHERE a=1;

表t1中,存在(a是唯一索引,b是唯一索引),则上述sql语句等同于

if(表中不存在(a=1 and b=2) 的数据) :
   INSERT INTO t1 (a,b,c) VALUES (1,2,3)  
else  
   UPDATE t1 SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

对于ON DUPLICATE KEY UPDATE语句的返回值
1:插入了一个新行
2: 更新已存在的数据
0: 已存在的数据值就是当前要更新的值

<think> 我们被要求解释MySQL中的ON DUPLICATE KEY UPDATE用法。根据引用[1][2][3][4],我们可以总结如下: 1. 功能:用于处理当插入的数据会导致唯一键(主键或唯一索引)冲突时,转而执行更新操作。 2. 语法:在INSERT语句后添加ON DUPLICATE KEY UPDATE子句,指定更新哪些列。 3. 注意事项: - 只适用于有唯一键或主键的表 - 使用VALUES()函数可以引用插入语句中本应插入的值 - 如果没有重复键,则正常插入;如果有,则更新 - 在批量插入时,ON DUPLICATE KEY UPDATE会对每一行可能冲突的记录进行更新 我们将详细解释并提供示例。 ### 一、基本语法 ```sql INSERT INTO table_name (col1, col2, ...) VALUES (val1, val2, ...) ON DUPLICATE KEY UPDATE col1 = new_val1, col2 = new_val2, ...; ``` ### 二、使用场景 当插入数据时,如果唯一键(主键或唯一索引)发生冲突,则执行UPDATE操作;否则执行INSERT操作。 ### 三、核心机制 1. **检测冲突**:根据主键或唯一索引判断是否重复 2. **更新操作**:使用UPDATE子句更新指定列 3. **引用原值**:通过`VALUES(列名)`获取原INSERT语句中的值 ### 四、示例说明 #### 示例1:基础更新 ```sql -- 假设id为主键 INSERT INTO users (id, name, age) VALUES (1, 'Alice', 25) ON DUPLICATE KEY UPDATE name = VALUES(name), age = VALUES(age); ``` - 若id=1不存在:插入新记录 - 若已存在:更新name和age为VALUES提供的值(即'Alice'和25) #### 示例2:表达式更新 ```sql INSERT INTO sales (product_id, quantity) VALUES (100, 5) ON DUPLICATE KEY UPDATE quantity = quantity + VALUES(quantity); -- 累加数量 ``` - 冲突时:将原有quantity增加5 ### 五、批量操作 ```sql INSERT INTO users (id, name) VALUES (1, 'Bob'), (2, 'Cindy'), (3, 'David') ON DUPLICATE KEY UPDATE name = VALUES(name); ``` - 对每一行独立判断:若某行冲突则更新该行,否则插入 ### 六、注意事项 1. **唯一键要求**:必须有主键或唯一索引(否则等同于普通INSERT) 2. **多唯一键冲突**:如果存在多个唯一键,只要有一个唯一键冲突就会触发更新(且按表定义顺序第一个冲突的键生效) 3. **VALUES()函数**:仅在UPDATE子句中有效,返回当前插入行的值 4. **影响行数**: - 插入成功:返回1 - 更新成功:返回2(删除旧行+插入新行计为2,但实际更新为1行) - 更新但数据无变化:返回0(如更新值与原值相同) ### 七、性能特点 1. 比先查询后更新效率更高(减少网络交互) 2. 比`REPLACE INTO`更优(`REPLACE`会先删除再插入,可能影响自增ID) ### 八、与标准SQL对比 MySQL不支持`MERGE INTO`语句,`ON DUPLICATE KEY UPDATE`是其特有实现,功能类似但语法更简洁。 §§相关问题§§ 1. ON DUPLICATE KEY UPDATE在批量插入时如何保证原子性? 2. 使用VALUES()函数有什么限制? 3. 多唯一键冲突时具体如何处理? 4. 如何获取ON DUPLICATE KEY UPDATE影响的行数? 5. 在InnoDB事务中,ON DUPLICATE KEY UPDATE会加什么类型的锁?[^1] [^1]: 引用自用户提供的参考内容 </think>### MySQL `ON DUPLICATE KEY UPDATE` 用法详解 #### 一、核心功能 当插入数据导致**唯一键(主键或唯一索引)冲突**时,自动转为执行更新操作。这是MySQL实现"插入或更新"(UPSERT)的高效方式[^1][^2]。 #### 二、基本语法 ```sql INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...) ON DUPLICATE KEY UPDATE 列1 = 新值1, 列2 = 新值2; ``` #### 三、使用场景 1. **主键冲突时更新** ```sql -- id为主键,冲突时更新name和age INSERT INTO users (id, name, age) VALUES (1, 'Alice', 25) ON DUPLICATE KEY UPDATE name = VALUES(name), age = VALUES(age); ``` 2. **唯一索引冲突处理** ```sql -- email字段有唯一索引 INSERT INTO customers (email, orders) VALUES ('alice@example.com', 1) ON DUPLICATE KEY UPDATE orders = orders + VALUES(orders); -- 订单数累加 ``` #### 四、核心函数:`VALUES()` 在UPDATE子句中通过`VALUES(列名)`引用**原INSERT语句中的值**[^3]: ```sql INSERT INTO products (id, stock) VALUES (101, 10) ON DUPLICATE KEY UPDATE stock = stock + VALUES(stock); -- 库存增加而非覆盖 ``` #### 五、批量操作 一次处理多行数据,每行独立判断冲突[^3]: ```sql INSERT INTO employees (id, salary) VALUES (101, 5000), (102, 6000), (103, 7000) ON DUPLICATE KEY UPDATE salary = VALUES(salary) * 1.1; -- 冲突时工资涨10% ``` #### 六、执行结果判断 通过返回值确定操作类型: - **0**:更新但数据无变化 - **1**:成功插入新行 - **2**:成功更新现有行 #### 七、注意事项 1. **必须存在唯一约束**(主键或唯一索引)[^2] 2. **多列唯一键冲突**:任一唯一键冲突都会触发更新 3. **自增ID处理**:更新时自增ID不会跳号(与`REPLACE INTO`不同) 4. **触发器触发**:同时触发`BEFORE INSERT`和`BEFORE UPDATE`触发器 #### 八、性能优势(vs 传统方式) | 操作方式 | 步骤数 | 网络请求 | 原子性 | |------------------------|--------|----------|--------| | `SELECT` + `INSERT/UPDATE` | 2-3 | 2-3 | ❌ | | `ON DUPLICATE KEY UPDATE` | 1 | 1 | ✔️ | #### 九、典型应用场景 1. **计数器累加** ```sql INSERT INTO page_views (page_id, views) VALUES (123, 1) ON DUPLICATE KEY UPDATE views = views + 1; ``` 2. **最后更新时间记录** ```sql INSERT INTO user_activity (user_id, last_active) VALUES (1001, NOW()) ON DUPLICATE KEY UPDATE last_active = NOW(); ``` 3. **数据同步** ```sql INSERT INTO target_table SELECT * FROM source_table ON DUPLICATE KEY UPDATE col1 = VALUES(col1), col2 = VALUES(col2); ``` > 💡 **最佳实践**: > - 优先使用`VALUES()`函数确保更新一致性 > - 批量操作时每批建议不超过1000行 > - 监控`innodb_autoinc_lock_mode`配置对并发的影响
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值