mysql避免重复插入记录insert ignore 、on duplicate key update、replace into

news2024/11/14 6:30:12

星标Java学习之道一起成长,一起学习~


哈喽,大家好,我是阿淼。今天梳理一下mysql中避免重复插入记录的集中操作。

1序

回顾以前写的项目,发现在规范的前提下,还是可以做点骚操作的。

假如项目使用的MySQL,首先创建测试数据表(建表语句中默认使用utf8mb4以及utf8mb4_unicode_ci,感兴趣的读者可以自行搜索这两个配置):

CREATE TABLE `student` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `no` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '编号',
  `name` varchar(30) NOT NULL COMMENT '名称',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unq_no` (`no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

utf8mb4是utf8的超集并完全兼容utf8,能够用四个字节存储更多的字符。例如emoji和一些不常用的汉字,如“墅”,这些需要四个字节才能编码的就不支持。

utf8mb4对应的排序字符集有utf8mb4_unicode_ci、utf8mb4_general_ci

utf8mb4_unicode_ci和utf8mb4_general_ci的对比

准确性:

  • utf8mb4_unicode_ci是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序

  • utf8mb4_general_ci没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。

  • 但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。

性能:

  • utf8mb4_general_ci在比较和排序的时候更快

  • utf8mb4_unicode_ci在特殊情况下,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

  • 但是在绝大多数情况下发,不会发生此类复杂比较。相比选择哪一种collation,使用者更应该关心字符集与排序规则在db里需要统一。

2插入冲突时更新数据 ON DUPLICATE KEY UPDATE

SQL执行插入时,可能因为种种原因插入失败,比如UNIQUE索引冲突导致插入失败。比如某个不晓得DBA插入了一条错误的学生记录("3", "小明"),悲剧的是小明的编号是1。常规做法就是判断当前的数据库记录中是否存在小明的记录,如果有则更新其对应其编号,否则就插入小明的记录。当然存在更好的做法:

INSERT INTO student(no, name) VALUES (3, "xiaoming");
INSERT INTO student(no, name) VALUES (1, "xiaoming"), (2,"xiaohong")
ON DUPLICATE KEY UPDATE no=VALUES(no);

那就是使用ON DUPLICATE KEY UPDATE,这是mysql独特的语法(语句后面可以放置多个更新条件,每个条件使用逗号隔开即可)。需要注意,这里的VALUES(no)是将冲突的no数值更新为用户插入数据中的no,这样每条冲突的数据就可以动态的设置新的数值。

// 标准用法,在插入末尾添加 on duplicate key updat
insert into tb(...) value(...) on duplicate key update no=values(no);

on duplicate key update 含义:

  • 1)如果在INSERT语句末尾指定了 on duplicate key update,如果插入会导致UNIQUE索引或PRIMARY KEY出现重复值,则在出现重复值的行执行UPDATE;

  • 2)如果不会导致唯一值列重复的问题,则插入新行。values(col_name)函数只是取当前插入语句中的插入值,并没有累加功能。

如:no = values(no) 取前面 insert into 中的 no 值,并更新当有多条记录冲突,需要插入时,前面的更新值都被最后一条记录覆盖,所以呈现出取最后一条更新的现象。

如:no = no + values(no) 依然取前面 insert into 中的 no 值,并与原记录值相加后更新回数据库,这样,当多条记录冲突需要插入时, 就实现了不断累加更新的现象。

有一些场景,如日志文件解析入库,消息队列接收数据入库等情况下可能解析到或者接收到待插入的重复数据xxx,存在重复数据则更新,不存在则插入。

3忽略插入失败中的错误 INSERT INTO

批量插入比单条数据挨个插入,普遍会提高性能以及减少总的网络开销。但是,假如批量插入的数据中心存在一个臭虫,在默认的情况下,这就会导致批量插入失败(没有一条数据插入成功)。当然,我们可以选择忽略。

// 标准用法
insert ignore into tb(...) value(...)
INSERT INTO student(`no`, `name`) VALUES (1, "xiaoming");
INSERT IGNORE INTO student(`no`, `name`) VALUES (1, "xiaoming"), (2,"xiaohong"),(3, "xiaowang");

只需要在批量插入的语句中,插入IGNORE,那么某几条数据的插入失败就会被忽略掉,正确的数据依然可以插入库中。

PS: 但是,我建议这个功能谨慎使用,使用mysql数据库本身就是看中数据的正确性,没必要为了批量插入的性能而自动放弃数据的正确性。

INSERT IGNORE 还有些副作用

insert ignore的时候会对插入的每一行数据取S锁做unique id的检测,同时会对主键的自增id字段加写意向锁(insert intension),在unique key较为复杂的时候,检测unique key的时候会一直占用主键的插入意向锁,其他insert ignore也想给主键id加插入意向锁,导致死锁。以上情况是在mysql 8.x中发现的,以前用低版本的mysql似乎没遇到过相关问题,所以不清楚低版本mysql的insert ignore是否有坑,但是8.x的版本最好insert ignore不要插入多行数据,尤其是unique key比较复杂的时候(有三四个字段共同组成)。

INSERT IGNORE其他些副作用,感兴趣的可以自行查询了解。

4插入替换数据 REPLACE INTO

如果存在primary or unique相同的记录,则先删除掉。再插入新记录。

这种方法就是不管原来有没有相同的记录,都会先删除掉然后再插入。

:插入数据的表必须有主键或者是唯一索引!否则的话,replace into 会直接插入数据,这将导致表中出现重复的数据。

// 第1种形式
replace into tbl_name(col_name, ...) values(...)
// 第2种形式
replace into tbl_name(col_name, ...) select ...
// 第3种形式
replace into tbl_name set col_name=value, ...
  • 第一种形式类似于insert into的用法,

  • 第二种replace select的用法也类似于insert select,这种用法并不一定要求列名匹配,事实上,MYSQL甚至不关心select返回的列名,它需要的是列的位置。

例如,replace into tb1( name, title, mood) select rname, rtitle, rmood from tb2;这个例子使用replace into从tb2中将所有数据导入tb1中。

  • 第三种replace set用法类似于update set用法,使用一个例如SET col_name = col_name + 1的赋值,则对位于右侧的列名称的引用会被作为DEFAULT(col_name)处理。因此,该赋值相当于SET col_name = DEFAULT(col_name) + 1。

PS: 前两种形式用的多些。其中 “into” 关键字可以省略,不过最好加上 “into”,这样意思更加直观。另外,对于那些没有给予值的列,MySQL 将自动为这些列赋上默认值。

5小结

replaceinsert...on duplicate key update 不同之处:

  • replace是删除记录,然后再重新insert

  • 而insert...on duplicate key update是直接在该条记录上修改

所以二者的差别主要有以下两处:

  • 1、当表中存在自增值的时候,如果表中存在某条记录,replace语法会导致自增值+1,而insert...on duplicate key update语法不会;

  • 2、当表中的某些字段中包含默认值的时候,replace操作插入不完全字段的记录,会导致其他字段直接使用默认值,而insert...on duplicate key update操作会保留该条记录的原有值。

-- END --

 
 
如果看到这里,说明你喜欢这篇文章,那就转发、点赞、在看三连吧。如果你有任何疑问,也欢迎找我沟通和交流。
▽加我微信,交个朋友

23d03690f7f24905ca3a7f8581a72b56.jpeg

长按/扫码添加↑↑↑

7c9190311bed6baa568fa280bca70efc.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/672503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Informer的股票价格预测(量化交易综述)

摘要 股票市场是金融市场中不可或缺的组成部分。准确预测股票趋势对于投资者和市场参与者具有重要意义,因为它们可以指导投资决策、优化投资组合以及降低金融风险。而且可以提升国家国际地位以及金融风险控制能力,还可以促进股票市场发展以及资源优化利…

Java常用类库与技巧

1、String,StringBuffer,StringBuilder的区别? 2、Java异常 异常处理机制主要回答了三个问题 What:异常类型回答了什么被抛出?Where:异常堆栈跟踪回答了在哪抛出?Why:异常信息回答…

PowerDesigner165安装

PowerDesigner安装及解析 一、PowerDesigner安装1.双击开始安装2.一路“Next”3.选择地区4.安装路径5.按图勾选6.一路“Next”7.安装中8.安装完成 二、解析三、使用 一、PowerDesigner安装 1.双击开始安装 2.一路“Next” 3.选择地区 选择软件安装所属地区,一定要选择“Hong …

vue3-实战-12-管理后台-权限管理之菜单管理模块-首页-主题颜色-暗黑模式

目录 1-列表页面功能开发 1.1-需求原型分析 1.2-接口和数据类型定义 1.3-获取服务端数据渲染页面 2-新增编辑菜单 2.1-原型需求分析 2.2-表单数据收集和页面结构开发 2.3-提交或者取消 3-删除菜单 4-首页开发 5-暗黑模式的切换和主题颜色 5.1-暗黑模式 5.2-主题颜…

three.js几何体的_UV_、法向属性以及BufferGeometry类介绍

一、几何体的_UV_以及法向属性 UV属性是一组二维坐标,每个顶点都有一个对应的UV坐标。在三维模型上贴上二维的纹理贴图时,需要将所有顶点映射到纹理上的对应位置。UV属性的取值范围一般是[0,1],表示纹理上的相对位置。通过修改UV属性&#xf…

Shell - 02_shell变量

一、shell的自定义变量 1.定义变量:变量名变量值 如:num10 2.引用变量:$变量名 如:i$num 把变量 num 的值付给变量 i 3.显示变量:使用 echo 命令可以显示单个变量取值 如:echo $num 4.清除变量&…

如何写好接口自动化测试脚本

谈到接口测试,大家关注更多的是哪个工具更优秀,更好用。但是很少人关注到接口测试用例的设计问题,也很少人会去写接口用例,都代码化了嘛,还写什么用例,是吧? 这样真的对么?我们是不…

Web3通过 MetaMask简单演示对ganache虚拟环境账号进行管理操作

上文 Web3通过ganache运行起一个本地虚拟区块链 我们通过ganache在本地运行起了一个虚拟的区块链环境 那么 接下来 我们就要用 MetaMask 来管理这个东西了 如果您还没有安装 可以访问文章Web3 将 MetaMask添加入谷歌浏览器 扩展程序中和Web3开发准备工作 手把手带你创建自己的 …

行业报告 | 人工智能时代的营销新趋势

原创 | 文 BFT机器人 01 科技推动时代发展进步 随着电子计算机的发明和使用,打开了人类知识的全方位信息时空,人类由此从工业文明走进信息文明,渐渐地网络成为了人们进行社会活动的基本平台。 智能手机的出现将人们剩余的碎片化时间也连接到了…

从尾到头打印链表

输入一个链表的头节点&#xff0c;按链表从尾到头的顺序返回每个节点的值&#xff08;用数组返回&#xff09;。 如输入{1,2,3}的链表如下图: ​ 返回一个数组为[3,2,1] 0 < 链表长度 < 10000 示例1 输入&#xff1a; {1,2,3} 返回值&#xff1a; [3,2,1]示例2 输入…

springboot集成J-IM+vue实现简单的聊天功能

前言&#xff1a;看了demo自己摸索着集成了一下&#xff0c;特此记录 一、引入依赖 <!-- jim-server --> <dependency><groupId>org.j-im</groupId><artifactId>jim-server</artifactId><version>3.0.0.v20200501-RELEASE&l…

【系统开发】尚硅谷 - 谷粒商城项目笔记(六):异步线程池

文章目录 异步线程池讲解简单线程池常见的四种线程池进阶线程池为什么使用线程池异步编排基本用法其他API线程串行化两任务组合都完成时一个完成时 多任务组合 异步线程池讲解 简单线程池 public class Test01 {public static void main(String[] args) {// 声明一个有10个线…

Java——集合

文章目录 1、集合概述2、集合类体系结构Collection集合体系 3、Collection集合常用API3、Collection集合的遍历方式方式一&#xff1a;迭代器方式二&#xff1a;foreach/增强for循环方式三&#xff1a;lambda表达式 4、List系列集合List集合特点和特有APILinkedList集合 5、集合…

物流园仓库智能综合监控系统

现代经济的不断发展&#xff0c;仓储物流业也在快速地发展&#xff0c;物流仓库作为物质资源的存储和转运&#xff0c;在经济生产中发挥着重大的作用&#xff0c;但是在此期间&#xff0c;随之而来的是物品丢失、被盗、损坏等一系列安全隐患事件。 物流仓库里面存储物品的多数都…

nginx: client intended to send too large body

最近上传大于1M文件的时候&#xff0c;报错nginx。 413 Request Entity Too Large 经过排查修改nginx配置 这是最简单的一个做法&#xff0c;着报错原因是nginx不允许上传配置过大的文件&#xff0c;那么件把nginx的上传大小配置调高就好。 1、打开nginx主配置文件nginx.co…

【性能测试】loadrunner12.55教程(一)--知识准备

目录 1.0. 前言 1.1 性能测试术语介绍 1.1.1 响应时间&#xff08;Response time&#xff09; 1.1.2 并发用户数 1.1.3 吞吐量&#xff08;Throughput&#xff09; 1.1.4 吞吐率&#xff08;Throughout&#xff09; 1.1.5 TPS&#xff08;Transaction Per Second&#x…

深度复盘:那些曾在618一鸣惊人的新品牌,今天过得怎么样?

分析师&#xff1a;yolo 编辑&#xff1a;yolo 出品&#xff1a;增长黑盒研究组 *本报告为增长黑盒独立研究系列&#xff0c; 与第三方不存在任何利益关系 从各平台的活动力度上来看&#xff0c;这届618堪称“史上最卷”&#xff1a;不装了&#xff0c;直接摊牌降价促销。 然而…

《VisualGLM-6B的原理与微调》资料学习分享

清华大学在发布chatGLM-6B后很快速的时间内就又发布了VisualGLM-6B模型&#xff0c;不可谓不强大&#xff0c;VisualGLM-6B官方项目地址在这里&#xff0c;如下所示&#xff1a; VisualGLM-6B 是一个开源的&#xff0c;支持图像、中文和英文的多模态对话语言模型&#xff0c;语…

2022前端趋势报告(上)

前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 一、前言 本文内容来自于《St…

N卡几千块的“智商税”,这下终于要没了

关于 CPU 显卡搭配&#xff0c;有句话大家肯定听过&#xff1a;「 i卡配iU、A卡配AU、N卡配 Fxxk U」 。 小白不要误会&#xff0c;这句话只是大家在喷N卡的定价问题。 拿刚刚过去的剁手节对比&#xff0c;AMD 这边旗舰显卡 RX 7900XT、XTX 价格直接跌到了 5/6000 出头。 而 …