mysql duplicate key与replace into对比
Posted PacosonSWJTU
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql duplicate key与replace into对比相关的知识,希望对你有一定的参考价值。
【REDME】
有些业务场景如下:
对于数据已经存在的,则更新;否则新增;
怎么判定数据已经存在,通过主键或唯一索引来判断;
业务场景:业务库的全局参数表的参数值的新增或更新就是 有则更细无则插入的常见业务场景;
【1】2种实现方式
通常情况下,我们是先select,判断数据是否存在;若不存在,则新增,否则更新;
要完成这个小小功能,我们需要写3条sql,非常麻烦;
采用2种简单方式(只需要写1条sql):
- 方式1, duplicate key, insert into ...... on duplicate key update ...
- 方式2,replace into,
【1.1】duplicate key update
0. duplicate 官方文档翻译,参见 https://blog.csdn.net/PacosonSWJTU/article/details/120058725
1.duplicate顾名思义,有重复键则更新,否则插入;
2.语法如下:
如果指定 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;
3.测试案例
-- 表结构
CREATE TABLE `my_cust_warn_tbl` (
`rcrd_id` varchar(64) NOT NULL COMMENT '记录编号',
`cust_num` varchar(50) NOT NULL COMMENT '客户号',
`cust_name` varchar(50) DEFAULT '' COMMENT '客户姓名',
`warn_times` int(11) DEFAULT NULL COMMENT '客户预警次数',
`create_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`last_modify_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '最后修改时间',
PRIMARY KEY (`rcrd_id`),
UNIQUE KEY `uni_cust_num` (`cust_num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户预警表'
注意: 使用duplicate语法的数据库表一定要设置唯一索引,以便于判断数据是否存在;
统计客户的预警次数,很显然就是有着更新,没有则新增;
INSERT INTO
mybatis.my_cust_warn_tbl (rcrd_id, cust_num, cust_name, warn_times)
VALUES('hand_11', 'hand_11_custnum', 'hand_11_custname', 0)
on duplicate key update warn_times=warn_times+1, create_time = current_timestamp
;
第一次执行上述sql,由于 hand_11_cust 不存在,则返回条数是1;
第二次执行SQL如下 (注意,第一次与第二次的sql不一样,主键不同,但客户号相同,客户号是唯一索引)
INSERT INTO
mybatis.my_cust_warn_tbl (rcrd_id, cust_num, cust_name, warn_times)
VALUES('hand_11_2', 'hand_11_custnum', 'hand_11_custname', 0)
on duplicate key update warn_times=warn_times+1, create_time = current_timestamp
;
由于 hand_11_cust 已经存在,更新条数返回2;
【1.2】replace into
1.replace顾名思义,替换,有则先删除,后插入;没有则直接插入;
步骤为:
- step1)delete 存在的记录(通过主键或唯一索引来判断);
- step2)重新插入新值;
为了演示效果,我们新建了一个主键自增的数据库表;
drop table if exists my_cust_warn_autopk_tbl
;
CREATE TABLE `my_cust_warn_autopk_tbl` (
`rcrd_id` int primary key not null auto_increment COMMENT '记录编号',
`cust_num` varchar(50) NOT NULL COMMENT '客户号',
`cust_name` varchar(50) DEFAULT '' COMMENT '客户姓名',
`warn_times` int(11) DEFAULT NULL COMMENT '客户预警次数',
`create_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`last_modify_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '最后修改时间',
UNIQUE KEY `uni_cust_num` (`cust_num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户预警表(自增)'
;
2. 测试案例
REPLACE INTO
mybatis.my_cust_warn_autopk_tbl (cust_num, cust_name, warn_times)
VALUES('hand_12_custnum', 'hand_12_custname', 0)
;
因为之前没有存在的数据,故更新行数为1;
刚刚插入的记录的主键值为1 ; 如下;
接着, 我们把客户姓名字段设置为null看下; 发现更新行数为2;
REPLACE INTO
mybatis.my_cust_warn_autopk_tbl (cust_num, cust_name, warn_times)
VALUES('hand_12_custnum', null, 0)
;
我们看下数据长什么样子:仅有一个 主键值为2的记录存在;
很显然,因为存在客户号为 hand_12_custnum的记录,于是先删除了 主键为1的记录,然后再插入主键为2的记录,如下:
当然了,通过两次sql的 create_time 也可以判断出 第2次replace是 删除旧记录,然后重新新增一条数据,而不是在旧记录上修改; 因为 两次的create_time 不一样;
【2】 两者执行时间简单对比
show variables like "%pro%";
set profiling=1;
show profiles ;
以上是关于mysql duplicate key与replace into对比的主要内容,如果未能解决你的问题,请参考以下文章
mysql duplicate key与replace into对比
MySQL的replace into 与insert into on duplicate key update
MySQL的replace into 与insert into on duplicate key update
mysql中的ON DUPLICATE KEY UPDATE