MySQL原生语句保存或更新的编写方法综述
背景在正常的开发中,我们经常遇到更新数据的场景:首先判断数据是否存在于库表中,有更新,并且没有插入。
如果使用的是Hibernate,可以很方便的使用saverorupdate方法,但如何使用SQL语句
初学者最常用的方法是先查询记录是否存在SELECT语句,然后使用UPDATE语句更新,不存在插入INSERT语句。
但这显然不够优雅,还有几个问题:
为了执行更新操作,程序中使用了两个SQL查询,当系统负载比较大时,性能仍会受到影响。
代码中有一个if语句,它清楚地做了一件事,但是代码很长。代码农民都是懒惰的人,为什么他们只做简单的事情:)。
所以问题是,你如何使用SQL语句来实现saverorupdate优雅
最近的工作也遇到了类似的问题,数据的更新,写的也开始感到恼火。记得有一个合并在甲骨文写作的方法,和一个类似的实现基于如下眉目传情:
数据不存在和插入,没有操作
忽略插入INSERT语句实现数据不存在关键词的使用,并没有运行。实现的逻辑是,INSERT语句或唯一键冲突发生主键冲突时,误差不扔,和插入语句直接忽略。到官方网站的相关介绍如下:
如果使用忽略关键字,则在执行INSERT语句时发生的错误将被忽略。例如,如果不忽略,复制表中现有的唯一索引或主键值的行会导致重复的关键错误,语句被终止。如果忽略,该行将被丢弃,不会发生错误。忽略的错误可能会产生警告,而不是重复的键,错误不会。
MySQL官方文档提供标准语法:
复制代码代码如下所示:
将忽略
为tbl_name
{分区(partition_name,…)}
{ }(col_name,…)
{价值}({ expr | |默认},…),(…),…
也许
复制代码代码如下所示:
将忽略
{在} tbl_name
{分区(partition_name,…)}
{ }(col_name,…)
选择…
除了一个以上的忽略关键字外,与一般INSERT语句没有区别。
栗子:
1。构建测试表
复制代码代码如下所示:
创建表(` test_tab `
`名字` varchar(64)不为空,
年龄int(11)不为空,
主键(名称)
InnoDB引擎=默认的字符集utf8);
2。插入一段数据
复制代码代码如下所示:
插入` test_tab `(`名字`,`年龄`)值('zhangsan ',24)
为test_tab表的当前数据:
复制代码代码如下所示:
名称|年龄
- |:—:—
24 | zhangsan
三.一步2插入语句的执行将报告异常:
复制代码代码如下所示:
{错误} 1062重复entry'zhangsan'for key'primary
4。将忽略关键字添加到步骤2的INSERT语句中,不报告异常,并且不更新现有的数据。
复制代码代码如下所示:
将忽略为` test_tab `(`名字`,`年龄`)值('zhangsan ',24);
。
语句执行:
受影响的线:0
时间:0.000s
为test_tab表的当前数据:
复制代码代码如下所示:
名称|年龄
- |:—:—
24 | zhangsan
没有存在是插入,存在是被更新的,一个(使用重复关键字更新关键字)
使用INSERT语句中的重复关键字更新关键字,插入数据,并更新现有操作。判断数据重复的逻辑仍然是主键冲突或唯一密钥冲突。
官方网站的相关介绍如下:
如果指定了重复密钥更新,并且插入了一个行,该行将导致唯一索引或主键中的重复值,则执行旧行的更新。每行的受影响行值是插入行1,如果现有行为新行,则更新为0,如果现有行设置为当前值,则行为2。
MySQL官方文档提供标准语法:
复制代码代码如下所示:
插入
{在} tbl_name
{分区(partition_name,…)}
{ }(col_name,…)
{价值}({ expr | |默认},…),(…),…
{重复密钥更新
col_name =表达式
{,col_name =表达式}…}
或:
复制代码代码如下所示:
插入
{在} tbl_name
{分区(partition_name,…)}
设置默认col_name = { } | expr,…
{重复密钥更新
col_name =表达式
{,col_name =表达式}…}
或:
复制代码代码如下所示:
插入
{在} tbl_name
{分区(partition_name,…)}
{ }(col_name,…)
选择…
{重复密钥更新
col_name =表达式
{,col_name =表达式}…}
可见,或原始插入语句的原始书写。
栗子:
1。利用新建的test_tab表,此表中的数据如下:
复制代码代码如下所示:
名称|年龄
- |:—:—
24 | zhangsan
2。使用同一主键的同一INSERT语句,仍然存在重复的密钥错误
复制代码代码如下所示:
插入` test_tab `(`名字`,`年龄`)值('zhangsan ',50);
—
{错误} 1062重复entry'zhangsan'for key'primary
三.加上重复的密钥更新的INSERT语句现在。关键词 uff1a
复制代码代码如下所示:
插入` test_tab `(`名字`,`年龄`)值('zhangsan ',50)
关于重复密钥更新'年龄= 50;
—
受影响的线:2
时间:0.025s
4。在这个时候is'zhangsan主键的数据,年龄字段已更新:
复制代码代码如下所示:
名称|年龄
- |:—:—
50 | zhangsan
5、当然,如果主键不冲突,效果与通常的INSERT语句相同:
复制代码代码如下所示:
插入` test_tab `(`名字`,`年龄`)值('lisi ',30)
关于重复密钥更新'年龄= 30;
—
受影响的线:1
时间:0.009s
复制代码代码如下所示:
名称|年龄
- |:—:—
50 | zhangsan
Lisi | 30
插入不存在的,存在的更新,和第二(使用REPLACE语句实现)
保存或更新在MySQL中有另一个实现,替换成语句,它与Oracle的合并有点类似。判断数据重复的逻辑仍然是主键或唯一键冲突:
复制代码代码如下所示:
{ } |取代low_priority延迟
{在} tbl_name
{分区(partition_name,…)}
{ }(col_name,…)
{价值}({ expr | |默认},…),(…),…
或:
复制代码代码如下所示:
{ } |取代low_priority延迟
{在} tbl_name
{分区(partition_name,…)}
设置默认col_name = { } | expr,…
或:
复制代码代码如下所示:
{ } |取代low_priority延迟
{在} tbl_name
{分区(partition_name,…)}
{ }(col_name,…)
选择…
栗子:
1。上述test_tab表数据仍被使用,此时的数据如下
复制代码代码如下所示:
名称|年龄
- |:—:—
50 | zhangsan
Lisi | 30
2。一般使用INSERT语句插入名称= zhangsan的数据和报告的主键冲突。但改变替换成…的说法是没有问题的:
复制代码代码如下所示:
替换成` test_tab `(`名字`,`年龄`)值('zhangsan ',30);
—
受影响的线:2
时间:0.009s
三.以下结果如下:
复制代码代码如下所示:
名称|年龄
- |:—:—
30 | zhangsan
Lisi | 30
对于操作的结果,它是非常喜欢保存或更新,但实施不同于重复密钥更新关键字插入。当替换语句,重复数据删除,然后将新数据插入,更新不更新,但删除> insert.in大多数情况下,这不是一个用替换来完成更新操作的问题,但有一个场景,必须特别注意:
当更新表的插入、更新和删除触发器的替换语句使用时必须特别小心。因为根据业务逻辑,数据更新后,应触发更新触发,但使用替换语句,将触发删除和插入触发器更新如果有一些特殊的操作触发(如记录操作日志)的话,使用替代会导致业务逻辑的混乱。
因此,当更新表有触发器场景时,使用插入的重复关键字更新关键字是更合适的。
以上是本文中描述的所有内容,我希望能让您更好地理解MySQL中的保存和更新语句。