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 ; 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值