Oracle 适配 OpenGauss 数据库差异SQL汇总

背景

国产化进程中,需要将某项目的数据库从 Oracle 转为 OpenGauss ,项目初期也是规划了适配不同数据库的,MyBatis 配置加载路径设计的是根据数据库类型加载指定文件夹的 xml 文件。

后面由于固定了数据库类型为 Oracle 后,只写了 Oracle 的没有其他类型。从 Oracle 适配 OpenGauss 多少还是有些差异 SQL 语法的,本文记录一下。

之前不太了解 OpenGauss,但是接触过盘维数据库,这俩都可以用 postgre 的 Java 数据库驱动,把它们都归于 postgre 来看就可以了,目前发现了一些适配问题,都一一解决了,汇总如下。

varchar2 类型

Oracle 的数据库建表语句中的 varchar2 类型,直接在 OpenGauss 数据库中执行,也能兼容,但是实际类型为 varchar 。

NCLOB 类型

Oracle 的 NCLOB 类型到了 OpenGauss 应该配置为 bytea 。

LISTAGG 函数

Oracle 有 LISTAGG 函数生成动态拼接的 SQL ,MySQL 对应的函数是 GROUP_CONCAT ,到了以 postgre 为内核的 OpenGauss 应该用 string_agg

主键索引名称

Oracle 创建表设置主键索引的时候,索引名称可以跟表名称相同,例如这个建表语句:

CREATE TABLE MY_TABLE_1(field_a VARCHAR2(32),field_b VARCHAR2(50),field_c VARCHAR2(255),field_d VARCHAR2(32),field_e VARCHAR2(2),constraint MY_TABLE_1 primary key(field_a)
) ;

建表语句在后面设置表的主键,主键索引名称配置的与表名称一样,这个对 Oracle 没问题。

但是到了 OpenGauss 的时候会报 relation “xxx” already exists ,但是实际上这个名称的表并没有创建:
在这里插入图片描述
解决办法:设置索引名称与表名不一样,比如加个前缀

distinct 与 order by 语法

对于 Oracle 数据库而已,使用 distinct 后 order by 的字段可以不包含在查询字段列表中,例如这个 SQL 语句是正确的在 Oracle 中:

SELECT DISTINCT field1,field2
FROM MY_TABLE
ORDER BY field3 DESC

但是在 OpenGauss 中报异常,SELECT DISTINCT ORDER BY 字段必须出现在查询字段列表中:
在这里插入图片描述
解决办法:统一 SQL 把排序字段加在查询字段列表中。

批量插入语法

Oracle 的批量插入 SQL 语句有两种方式,一种是用 begin end; 包裹的存储过程,另一种是使用 dual 中建表。

方法一:

<insert id="insertBatchSomeColumn" parameterType="java.util.List">begin<foreach collection="list" item="tempData" index="index" separator =";">INSERT INTO my_table(a,b,c,d)VALUES (#{tempData.a,jdbcType=VARCHAR},#{tempData.b,jdbcType=VARCHAR},#{tempData.c,jdbcType=VARCHAR},#{tempData.d,jdbcType=VARCHAR})</foreach>;end;
</insert>

方法二:

<insert id="insertBatchSomeColumn">INSERT INTO my_table(a, b, c, d)<foreach collection="list" item="item" index="index" separator="union all" open="("  close=")">select #{item.a,jdbcType=VARCHAR},#{item.b,jdbcType=VARCHAR},#{item.c,jdbcType=VARCHAR},#{item.d,jdbcType=VARCHAR} from dual</foreach>
</insert>

但是对于 OpenGauss 数据库的批量插入SQL 语法应该调整为:

<insert id="insertBatchSomeColumn" parameterType="java.util.List">INSERT INTO my_table(a,b,c,d) VALUES<foreach collection="list" item="tempData" index="index" separator =",">(#{tempData.a,jdbcType=VARCHAR},#{tempData.b,jdbcType=VARCHAR},#{tempData.c,jdbcType=VARCHAR},#{tempData.d,jdbcType=VARCHAR})</foreach>
</insert>

Quartz 兼容配置

使用了 Quartz 定时调度框架,当数据库换成 postgre 驱动的时候,需要调整 Quartz 的配置,主要有三点:

  1. 修改spring.quartz.properties.org.quartz.jobStore.driverDelegateClass 这个属性为org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
  2. Quartz 的初始化 SQL 语句导入需要修改,NCLOB 类型需要改为 bytea,例如:JOB_DATA bytea
  3. 调度任务的布尔字段类型,例如 QZ_CLS_JOB_DETAILS 表的 IS_DURABLEIS_NONCONCURRENTIS_UPDATE_DATA,需要从 varchar2(1) 改为 varchar(5)因为 Oracle 存储布尔字段时用的字符串 0 和 1但是 postgre 驱动用的是 true 和 false ,导致任务调度时出现字段超长异常。

字段大小写问题

Oracle 字段默认都是转化为大写的,MySQL 大小写不区分,但是 postgre 内核默认字段都是小写的。

这是比较麻烦的,如果查询语句中使用 Map 接收查询结果时,查询结果字段名称都转化为小写了。而从 Map 中 get 数据时的 key 都是大写的话,就会出现值为空的问题。

解决办法:自定义 MyBatis 的 Map 封装工厂,步骤如下:

第一步,定义 MapWrapper 实现子类定制查询结果的 Key 转为大写字母:

public class MyBatisCustomWrapper extends MapWrapper {public MyBatisCustomWrapper(MetaObject metaObject, Map<String, Object> map) {super(metaObject, map);}@Overridepublic String findProperty(String name, boolean useCamelCaseMapping) {// 转小写为toUpperCase()return name == null ? "" : name.toUpperCase();}
}

第二步,定义工厂类:

public class MyBatisMapWrapperFactory implements ObjectWrapperFactory {@Overridepublic boolean hasWrapperFor(Object object) {return object != null && object instanceof Map;}@Overridepublic ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {return new MyBatisCustomWrapper(metaObject,(Map)object);}
}

第三步,注入定制工厂:

@Bean
public ConfigurationCustomizer mapUpgrade() {return configuration -> configuration.setObjectWrapperFactory(new MyBatisMapWrapperFactory());
}

启示录

目前发现的就是这些问题,解决的还是比较顺利的。还是需要对整个系统的功能逐个进行测试,直接用 MyBatis 的框架封装的方法没有问题,麻烦的是各种通过 @Select 注解嵌入在代码中的SQL语句,需要逐个排查。

一开始约定好SQL语句都在 resource 中定义的话,相对会比较好一点,如果有不同的话,就可以放在不同目录里面通过 mybatis-plus.mapper-locations 配置来指定。但是在 DAO 里面定义的 SQL 就必须通过定义多个方法来区分了。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从开始实现扩散概率模型 PyTorch 实现

目录 一、说明 二、从头开始实施 三、线性噪声调度器 四、时间嵌入 五、下层DownBlock类块 六、中间midBlock类块 七、UpBlock上层类块 八、UNet 架构 九、训练 十、采样 十一、配置&#xff08;Default.yaml&#xff09; 十二、数据集 (MNIST) keyword&#xff1a; Diffusion…

CCF-GESP 等级考试 2024年12月认证C++七级真题解析

2024年12月真题 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 正确答案&#xff1a;D 解析&#xff1a;考察字符类型和ASCII码值。 字符类型参与运算&#xff0c;是它所对应的ASCII码值在参与运算&#xff0c;运算结果为整数值。小写字母 b 的ASCII码为98&am…

递归实现指数型枚举(递归)

92. 递归实现指数型枚举 - AcWing题库 每个数有选和不选两种情况 我们把每个数看成每层&#xff0c;可以画出一个递归搜索树 叶子节点就是我们的答案 很容易写出每dfs函数 dfs传入一个u表示层数 当层数大于我们n时&#xff0c;去判断每个数字的选择情况&#xff0c;输出被选…

事务-介绍与操作四大特性

一.数据准备&#xff1a; 1.员工表&#xff1a; -- 员工管理 create table tb_emp (id int unsigned primary key auto_increment comment ID,username varchar(20) not null unique comment 用户名,password varchar(32) default 123456 comment 密码,n…

[白月黑羽]关于风机协议工具的解答

架构 python3.8pyqt5 先来看下原题&#xff1a; 视频中软件的效果 先来看下程序的效果如何&#xff0c;看上去大概相似 对应代码已经上传到了gitcode https://gitcode.com/m0_37662818/fan_protocol_tool/overview 实现中的难点是双悬浮可视化&#xff0c;同时要高亮悬浮对…

HCIA-Access V2.5_4_1_1路由协议基础_IP路由表

大型网络的拓扑结构一般会比较复杂&#xff0c;不同的部门&#xff0c;或者总部和分支可能处在不同的网络中&#xff0c;此时就需要使用路由器来连接不同的网络&#xff0c;实现网络之间的数据转发。 本章将介绍路由协议的基础知识、路由表的分类、静态路由基础与配置、VLAN间…

ISCTF复现-misc

File_Format 下载附件后用010打开查看文件头会发现是个exe文件 格式&#xff1a;文件描述&#xff08;后缀名&#xff09;&#xff0c;文件头(hex)&#xff1a;文件头标识&#xff08;十六进制&#xff09;PNG (png)&#xff0c;文件头(hex)&#xff1a;89504E47 PNGImageFile…

Windows设置所有软件默认以管理员身份运行

方法一、修改注册表 winr打开运行&#xff0c;输入“regedit”打开注册表&#xff1b; 打开此路径“计算机HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionPoliciesSystem”&#xff1b; 在右侧找到“EnableLUA”&#xff0c;将其值改为0&#xff0c;重启电脑。 …

【题解】—— LeetCode一周小结50

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结49 9.判断国际象棋棋盘中一个格子的颜色 题目链接&#xff1a;…

Docker安全性与最佳实践

一、引言&#xff1a;Docker安全性的重要性 Docker作为一种容器化技术&#xff0c;已成为现代应用程序部署和开发的核心工具。然而&#xff0c;随着容器化应用的普及&#xff0c;Docker的安全性问题也日益突出。容器本身的隔离性、网络配置、权限管理等方面的安全隐患&#xf…

利用notepad++删除特定关键字所在的行

1、按组合键Ctrl H&#xff0c;查找模式选择 ‘正则表达式’&#xff0c;不选 ‘.匹配新行’ 2、查找目标输入 &#xff1a; ^.*关键字.*\r\n (不保留空行) ^.*关键字.*$ (保留空行)3、替换为&#xff1a;&#xff08;空&#xff09; 配置界面参考下图&#xff1a; ​​…

上传图片的预览

解决:在上传图片时,1显示已有的图片 2显示准备替换的图片 前 后 在这个案例中可以预览到 【已有与准备替换】 2张图片 具体流程 1创建一个共享组件 与manage.py同级别路径的文件 manage.py custom_widgets.py# custom_widgets.py from django import forms from dja…

MySQL学习之DDL操作

目录 数据库的操作 创建 查看 选择 删除 修改 数据类型 表的创建 表的修改 表的约束 主键 PRIMARY KEY 唯一性约束 UNIQUE 非空约束 NOT NULL 外键约束 约束小结 索引 索引分类 常规索引 主键索引 唯一索引 外键索引 优点 缺点 视图 创建 删除 修改…

国际网络专线是什么?有什么优势?

国际网络专线作为一种独立的网络连接方式&#xff0c;通过卫星或海底光缆等物理链路&#xff0c;将全球不同国家和地区的网络直接互联&#xff0c;为企业提供了可靠的通信渠道。本文将详细探讨国际网络专线的优势以及其广泛的应用场景。 国际网络专线的优势解析 1. 专属连接&am…

密码编码学与网络安全(第五版)答案

通过如下代码分别统计一个字符的频率和三个字符的频率&#xff0c;"8"——"e"&#xff0c;“&#xff1b;48”——“the”&#xff0c;英文字母的相对使用频率&#xff0c;猜测频率比较高的依此为&#xff09;&#xff0c;t,*,5&#xff0c;分别对应s,o,n,…

【功能安全】随机硬件失效导致违背安全目标的评估(FMEDA)

目录 01 随机硬件失效介绍 02 FMEDA介绍 03 FMEDA模板 01 随机硬件失效介绍 GBT 34590 part5

mybatis 的动态sql 和缓存

动态SQL 可以根据具体的参数条件&#xff0c;来对SQL语句进行动态拼接。 比如在以前的开发中&#xff0c;由于不确定查询参数是否存在&#xff0c;许多人会使用类似于where 1 1 来作为前缀&#xff0c;然后后面用AND 拼接要查询的参数&#xff0c;这样&#xff0c;就算要查询…

Web APIs - 第5章笔记

目标&#xff1a; 依托 BOM 对象实现对历史、地址、浏览器信息的操作或获取 具备利用本地存储实现学生就业表案例的能力 BOM操作 综合案例 JavaScript的组成 ECMAScript: 规定了js基础语法核心知识。 比如&#xff1a;变量、分支语句、循环语句、对象等等 Web APIs : DO…

AI视频配音技术创新应用与商业机遇

随着人工智能技术的飞速发展&#xff0c;AI视频配音技术已经成为内容创作者和营销人员的新宠。这项技术不仅能够提升视频内容的吸引力&#xff0c;还能为特定行业带来创新的解决方案。本文将探讨AI视频配音技术的应用场景&#xff0c;并讨论如何合法合规地利用这一技术。 AI视频…

vlan和vlanif

文章目录 1、为什么会有vlan的存在2、vlan(虚拟局域网)1、vlan原理1. 为什么这样划分了2、如何实现不同交换机相同的vlan实现互访呢3、最优化的解决方法&#xff0c;vlan不同交换机4、vlan标签和vlan数据帧 5、vlan实现2、基于vlan的划分方式1、基于接口的vlan划分方式2、基于m…