当前位置: 首页 > news >正文

Mybatis XML 数据源为 Oracle 之批量插入或更新 Merge Into 的具体介绍与使用

文章目录

  • 声明
  • 一、前言
    • 1、MergeInto简介
    • 2、MergeInto批量插入更新
    • 3、带有CLOB类型字段的MergeInto

声明

  1. 原文地址:https://blog.csdn.net/qq_42142477/article/details/115198285

一、前言

  • 由于近期在所开发的项目中,对于数据入库,有 存在即更新,不存在则插入 的需求,因此发现了 Oracle中的 MergeInto 命令。本文将对MergeInto的用法进行介绍并将 MergeInto 和批量插入进行结合,同时还会对在 MergeInto 开发中遇到的问题进行总结。

1、MergeInto简介

  • MergeInto 命令是 Oracle9i 中新增的命令,有了 MergeInto 语句,我们对数据能够不仅仅只做单一的插入或单一的更新,而是可以将更新与插入一起操作。

  • MergeInto通过对两张表进行连接比较,如果匹配则 UPDATE,否则 INSERT

语法

MERGE INTO table_name a
USING ((table|view|sub_query)
) b
ON (condition) 
WHEN MATCHED THENmerge_update
WHEN NOT MATCHED THENmerge_insert

举例

MERGE INTO USER a
USING (select * from USER
) b
ON (condition) 
WHEN MATCHED THENmerge_update
WHEN NOT MATCHED THENmerge_insert
  • 注意
  1. 此处的update语句与平时我们写的update语句不同,update和set之间不能有表名,否则会报缺少SET关键字
  2. update语句中不能存在在ON中进行匹配后的字段,否则会报无法更新 ON 子句中引用的列A.USERID
    错误❌:
MERGE INTO USER a
USING (select #{user.userid} as id from dual
) b
ON (a.USER_ID = b.id) 
WHEN MATCHED THENUPDATE SET USER USER_ID = b.idUSER_NAM = b.usernameWHERE USER_ID = b.userid
WHEN NOT MATCHED THENmerge_insert

正确✔:

MERGE INTO USER a
USING (select #{user.userid} as id from dual
) b
ON (a.USER_ID = b.userid) 
WHEN MATCHED THENUPDATE SET USER USER_NAM = b.usernameWHERE USER_ID = b.userid
WHEN NOT MATCHED THENmerge_insert
  1. update语句中不能在update中使用ON连接条件中的命名,否则会报B.USERID标识符无效
    错误❌:
MERGE INTO USER a
USING (select #{user.userid} as id from dual
) b
ON (a.USER_ID = b.userid) 
WHEN MATCHED THENUPDATE SET USER USER_ID = b.useridUSER_NAM = b.usernameWHERE USER_ID = b.userid
WHEN NOT MATCHED THENmerge_insert

正确✔:

MERGE INTO USER a
USING (select #{user.userid} as id from dual
) b
ON (a.USER_ID = b.userid) 
WHEN MATCHED THENUPDATE SET USER USER_NAM = b.usernameWHERE USER_ID = b.userid
WHEN NOT MATCHED THENmerge_insert
  1. 关于MergeInto只能更新不能插入(Updates:0)
    merge into a using on b,a、b表进行比较
情况结果
a存在,b不存在nothing
a存在,b存在update
a不存在,b存在insert b into a
a不存在,b不存在nothing

错误❌:如果是第一次入库,b必然为null

MERGE INTO USER a
USING (select #{user.userid} as id from USER
) b
ON (a.USER_ID = b.userid) 
WHEN MATCHED THENUPDATE SET USER USER_ID = b.useridUSER_NAM = b.usernameWHERE USER_ID = b.userid
WHEN NOT MATCHED THENmerge_insert

正确✔:

MERGE INTO USER a
USING (select #{user.userid} as id from dual
) b
ON (a.USER_ID = b.userid) 
WHEN MATCHED THENUPDATE SET USER USER_NAM = b.usernameWHERE USER_ID = b.userid
WHEN NOT MATCHED THENmerge_insert

2、MergeInto批量插入更新

  • 我们已经知道批量入库是将一个list作为整体进行入库操作,那么MergeInto和批量入库结合起来应该怎么写呢?又会有什么问题?

传统的批量入库

insert into USER(
USER_ID,USER_NAM
)
<foreach collection="list" item="item" index="index" separator="union all">(SELECT#{item.userid},#{item.username}FROM DUAL)
</foreach>

MergeInto批量

MERGE INTO USER a
USING (<foreach collection="list" item="item" index="index" separator="union all">(SELECT#{item.userid,jdbcType=VARCHAR} as userid,#{item.username,jdbcType=VARCHAR} as usernameFROM DUAL)</foreach>
) b
ON (a.USER_ID = b.userid) 
WHEN MATCHED THENUPDATE SET USER USER_NAM = b.usernameWHERE USER_ID = b.userid
WHEN NOT MATCHED THENINSERT(USER_ID,USER_NAM)VALUES(b.userid,b.username)
)

注意

  • 采取批量入库的时候,同一批的数据无法进行存在更新,不存在插入。因为同一批的数据不在比较范围内。
  • 解决方法:目前我还没有找到怎么在数据库语句中进行优化解决,但是我们可以在代码逻辑中,对list进行一个判断,如果已存在,则不执行list.add()。通过代码和数据库结合的方法,就可以避免上述情况了。

3、带有CLOB类型字段的MergeInto

  • 如果说我们将带有CLOB类型字段的sql按照上述语句去写,代码执行过程中会报错:java.sql.SQLSyntaxErrorException:ORA-01790:表达式必须具有对应表达式相同的数据类型。

  • 因此,针对带有CLOB类型字段的sql有两种写法:

  • 写法1

begin<foreach collection="list" item="item" index="index">MERGE INTO USER aUSING (SELECT#{item.userid,jdbcType=VARCHAR} as userid,#{item.username,jdbcType=CLOB} as usernameFROM DUAL)bON (a.USER_ID = b.userid) WHEN MATCHED THENUPDATE SET USER USER_NAM = b.usernameWHERE USER_ID = b.useridWHEN NOT MATCHED THENINSERT(USER_ID,USER_NAM)VALUES(b.userid,b.username);</foreach>
end; 
  • 写法2
    • 将empty_clob()代替要插入的clob数据,再用真正的数据去替换empty_clob()
    • 注意: 要对clob字段进行非空判断,不然当clob为空时会报错
begin<foreach collection="list" item="item" index="index">MERGE INTO USER aUSING (SELECT#{item.userid,jdbcType=VARCHAR} as userid,empty_clob() as usernameFROM DUAL)bON (a.USER_ID = b.userid) WHEN MATCHED THENUPDATE SET USER USER_NAM = b.usernameWHERE USER_ID = b.useridWHEN NOT MATCHED THENINSERT(USER_ID,USER_NAM)VALUES(b.userid,b.username);<if test="item.vluResume != null">update USER set USER_NAM = #{item.username,jdbcType=CLOB} where USER_ID = #{item.userid,jdbcType=VARCHAR} ;</if></foreach>
end;

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Android MediaRecorder 视频录制及报错解决
  • 【ubuntu24.04】docker安装
  • 7za解压缩工具
  • 常见漏洞描述及修复建议
  • SSv2数据集
  • QML基础学习
  • C++ 126类和对象_面像对像_继承
  • matlab 音频音量处理(音量大小按照dB调节)
  • 硬件工程师必须掌握的MOS管详细知识
  • QT stackwidget控件支持上下,左右手势滑动,触摸屏
  • Rust 面向对象编程
  • HTML静态网页成品作业(HTML+CSS)——花主题介绍网页设计制作(1个页面)
  • 解密键盘输入:探索设备控制器的奥秘
  • 基于STM32开发的智能家居照明控制系统
  • 港湾周评|IPO底稿的“萝卜章”与鸭脖大王被立案调查
  • angular2 简述
  • js ES6 求数组的交集,并集,还有差集
  • magento 货币换算
  • vue.js框架原理浅析
  • 大型网站性能监测、分析与优化常见问题QA
  • 大主子表关联的性能优化方法
  • 猴子数据域名防封接口降低小说被封的风险
  • 使用 QuickBI 搭建酷炫可视化分析
  • 使用API自动生成工具优化前端工作流
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • ​​​【收录 Hello 算法】10.4 哈希优化策略
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #HarmonyOS:基础语法
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (1)Hilt的基本概念和使用
  • (2015)JS ES6 必知的十个 特性
  • (4)事件处理——(7)简单事件(Simple events)
  • (vue)el-tabs选中最后一项后更新数据后无法展开
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (一)基于IDEA的JAVA基础1
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .FileZilla的使用和主动模式被动模式介绍
  • .form文件_SSM框架文件上传篇
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Framework 3.5安装教程
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET开源项目介绍及资源推荐:数据持久层
  • .NET牛人应该知道些什么(2):中级.NET开发人员
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @SpringBootApplication 包含的三个注解及其含义
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • [20170705]diff比较执行结果的内容.txt
  • [2021 蓝帽杯] One Pointer PHP