MySQL的ON DUPLICATE KEY UPDATE用法

本文详细介绍了在MySQL中如何使用ONDUPLICATEKEYUPDATE语句来高效地处理数据插入和更新操作,避免了传统方法下执行两次SQL所带来的效率低下和并发问题,确保了操作的原子性和数据完整性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平时我们在设计数据库表的时候总会设计 unique  或者 给表加上 primary key 的限制条件.

 

此时 插入数据的时候 ,经常会有这样的情况:

我们想向数据库插入一条记录:

  若数据表中存在以相同主键的记录,我们就更新该条记录。

  否则就插入一条新的记录。

 

逻辑上我们需要怎么写:

$result = mysql_query('select * from xxx where id = 1');
$row = mysql_fetch_assoc($result);
if($row){
mysql_query('update ...');
}else{
mysql_query('insert ...');
}

 

但是这样写有两个问题

1、效率太差,每次执行都要执行2个sql
2、高并发的情况下数据会出问题,不能保证原子性 

 

 

还好MySQL 为我们解决了这个问题:我们可以通过 ON DUPLICATE KEY UPDATE  达到以上目的, 且能保证操作的原子性和数据的完整性。

 

ON DUPLICATE KEY UPDATE 可以达到以下目的:

向数据库中插入一条记录:

若该数据的主键值/ UNIQUE KEY 已经在表中存在,则执行更新操作, 即UPDATE 后面的操作。

否则插入一条新的记录。

 

示例:

 

Step1 . 创建表,插入测试数据

 

SET FOREIGN_KEY_CHECKS=0;


-- ----------------------------
-- Table structure for mRowUpdate
-- ----------------------------
DROP TABLE IF EXISTS `mRowUpdate`;
CREATE TABLE `mRowUpdate` (
  `id` int(11) NOT NULL,
  `value` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;


-- ----------------------------
-- Records of mRowUpdate
-- ----------------------------
INSERT INTO `mRowUpdate` VALUES ('1', 'sss');
INSERT INTO `mRowUpdate` VALUES ('2', 'szh');
INSERT INTO `mRowUpdate` VALUES ('3', '9999');
SET FOREIGN_KEY_CHECKS=1;

 

 

 

 

 

Step2 .测试 ON DUPLICATE KEY UPDATE 的使用方法:

 

 

INSERT INTO mRowUpdate(id,`value`) VALUES(3, 'SuperMan') ON DUPLICATE KEY UPDATE `value`='SuperMan';

 

 

 

 

Step3. 查询数据的变化情况

 

 

 

 

 

 

 

 

 

==========================     话外篇   ===============================

 

 

技巧:

 

技巧 1 :

 

ON DUPLICATE KEY UPDATE 特别适用于多行插入。如:

 

INSERT INTO `table` (`a`, `b`, `c`) VALUES (1, 2, 3), (4, 5, 6) ON DUPLICATE KEY UPDATE `c`=VALUES(`a`)+VALUES(`b`);

 

          Tips: VALUES()函数只在INSERT…UPDATE语句中有意义,其它时候会返回NULL。

 

 

 

 

 

注意事项:

 

注意 1:

 

若多个索引都冲突,则只有一条记录被修改。

 

 

create table test(
id int not null primary key,
num int not null UNIQUE key,
tid int not null
)
为了测试两个唯一索引都冲突的情况,然后插入下面的数据


insert into test values(1,1,1), (2,2,2);
然后执行:


insert into test values(1,2,3) on duplicate key update tid = tid + 1;
因为a和b都是唯一索引,插入的数据在两条记录上产生了冲突,然而执行后只有第一条记录被修改

### SQL Server 中实现类似 MySQL `ON DUPLICATE KEY UPDATE` 的方法 在 SQL Server 中,可以使用 `MERGE` 语句来实现类似于 MySQL 的 `ON DUPLICATE KEY UPDATE` 功能。`MERGE` 语句允许在一个原子操作中同时执行插入、更新或删除操作,具体取决于目标表和源数据之间的匹配情况。 以下是一个基于 SQL Server 的 `MERGE` 语句示例,展示如何实现类似功能: ```sql -- 创建一个示例表 CREATE TABLE TargetTable ( ID INT PRIMARY KEY, Name NVARCHAR(50), UpdateTime DATETIME ); -- 插入初始数据 INSERT INTO TargetTable (ID, Name, UpdateTime) VALUES (1, '张三', GETDATE()); -- 使用 MERGE 实现类似 ON DUPLICATE KEY UPDATE 的功能 MERGE INTO TargetTable AS Target USING (SELECT 1 AS ID, '李四' AS Name, GETDATE() AS UpdateTime) AS Source ON Target.ID = Source.ID WHEN MATCHED THEN UPDATE SET Target.Name = Source.Name, Target.UpdateTime = Source.UpdateTime WHEN NOT MATCHED THEN INSERT (ID, Name, UpdateTime) VALUES (Source.ID, Source.Name, Source.UpdateTime); ``` #### 解释 - `MERGE INTO TargetTable AS Target` 指定目标表为 `TargetTable`。 - `USING (...) AS Source` 定义源数据集,这里是一个内联查询结果。 - `ON Target.ID = Source.ID` 定义匹配条件,类似于 MySQL 中的主键或唯一键判断[^4]。 - `WHEN MATCHED THEN UPDATE ...` 表示当目标表中存在匹配记录时,执行更新操作。 - `WHEN NOT MATCHED THEN INSERT ...` 表示当目标表中不存在匹配记录时,执行插入操作。 这种语法与 MySQL 的 `ON DUPLICATE KEY UPDATE` 功能非常相似,但更灵活,支持更多复杂的场景[^5]。 --- ### 示例代码扩展 如果需要更新多个字段或处理复杂逻辑,可以扩展 `MERGE` 语句。例如: ```sql MERGE INTO TargetTable AS Target USING (SELECT 2 AS ID, '王五' AS Name, GETDATE() AS UpdateTime) AS Source ON Target.ID = Source.ID WHEN MATCHED THEN UPDATE SET Target.Name = CASE WHEN Target.Name <> Source.Name THEN Source.Name ELSE Target.Name END, Target.UpdateTime = GETDATE() WHEN NOT MATCHED THEN INSERT (ID, Name, UpdateTime) VALUES (Source.ID, Source.Name, Source.UpdateTime); ``` 上述代码中,`CASE` 语句用于确保仅在必要时更新某些字段[^3]。 --- ### 注意事项 - 在 SQL Server 中,`MERGE` 语句要求目标表和源数据集之间有明确的匹配条件。 - 如果需要根据多个唯一键进行判断,可以在 `ON` 子句中添加更多条件。 - 确保目标表的主键或唯一约束定义正确,否则可能导致意外行为[^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值