以MySQL数据库开发的内容管理系统,需要兼容Oracle数据库遇到的问题以及解决方案。
一、问题背景描述
开发的系统默认MySQL数据库,现在需要适合Oracle数据库,初始化数据库SQL和代码中包含MySQL的执行SQL需要重新定义。
二、目前遇见的问题(18.6.19)
1、Oracle的表名和列名长度只支持30个字符以内。
2、MySQL中ifnull()函数和format()函数等等等不存在于Oracle数据库中。
3、存储过程语法不同。
4、分页查询语法无法写出通用的SQL。
三、问题分析以及解决方案。
1、Oracle的表名和列名长度只支持30个字符以内。
解决方案:简化长度过长的表名和列名,新建更新SQL。
# 调整表WCMMetaTableGovDocSelfAssessment的名称为WCMMetaTableGovDocSelfAs(兼容oracle中表名的长度限制) alter table WCMMetaTableGovDocSelfAssessment rename WCMMetaTableGovDocSelfAs ; # 调整表列表名WCMMetaTableGovDocSelfAssessmentID的名称为WCMMetaTableGovDocSelfAsID(兼容oracle中表名的长度限制) ALTER TABLE WCMMetaTableGovDocSelfAs CHANGE WCMMetaTableGovDocSelfAssessmentID WCMMetaTableGovDocSelfAsID INT(11);2、MySQL中ifnull()函数和format()函数等等等不存在于Oracle数据库中。
(1)问题分析:Oracle不支持ifnull函数和format的函数,但是在统计类业务逻辑中使用大量的拼接SQL,因此目前解决的方案有两个,一个是修改为通用的SQL,一个是获取数据库信息,根据判断执行不同的SQL。
统计类业务中拼接SQL数量过于庞大,如果根据数据库写成两个逻辑,一方面是工作量过大,另一方面不断的请求数据库,会对服务器造成不必要的压力,并发越大,产生的性能影响就是之前的两倍。
最后,MySQL和Oracle都支持SQL99标准。
(2)解决方案:
目前在统计业务类中,主要涉及到的是ifnull和foamat这两个韩函数。因此,优先选择修改拼接SQL,使用共用的SQL。
(3)解决过程:
ifnull(EXPR1,EXPR2)的用法是EXPR1不为空返回EXPR1,否则返回EXPR2,一般返回的是数字或者字符串。
nullif(EXPR1,EXPR2)的用法是EXPR1等于EXPR2时,返回空,否则返回EXPR1。
在Oracle中,不支持ifnull,只支持nullif,MySQL中的ifnull等价于decode(),但是目前必须是要写一个通用的SQL,如果是能通用的函数就更好。
仔细的查询过Oracle的相关函数资料以后,找到了一个尽可能类似的函数COALESCE(EXPR1,EXPR2,EXPR3...EXPRn),然而测试过后,发现这个函数只支持字符串类型的数据。
最后只能选择使用case when else end 这个使用起来略繁杂的语法。
(4)代码案例
不兼容代码:
"FORMAT(IFNULL((COUNT( CASE WHEN STATUSID IN (19) THEN 0 END )/" + "COUNT(WORKORDERID))*100,0),0) as finalSolvedRate," +兼容代码:
"ROUND(CASE WHEN((COUNT( CASE WHEN STATUSID IN (19) THEN 0 END )/" + "COUNT(WORKORDERID))*100) IS NOT NULL THEN ((COUNT( CASE WHEN STATUSID IN (19) THEN 0 END )/" + "COUNT(WORKORDERID))*100) ELSE 0 END,0) as finalSolvedRate," +(5)format和round。
在MySQL中,format的用法是格式化数据,可支持数字、日期格式。round只支持数字格式。
3、存储过程语法不同
(1)问题分析:关于存储过程的语法不同,这个就没有办法兼容了,一般存储过程都是存在于初始化SQL里面,不会出现在代码中的拼接SQL。
(2)解决方案:新写一套Oracle版本初始化SQL。
4、分页查询语法无法写出通用的SQL
(1)问题分析:MySQL中可以使用limit来选择想要获取的数据,但是在Oracle中就只能使用伪列,伪列只能从一开始,必须要嵌套起来子查询。
(2)解决方案:因为代码中含有这个分页获取数据的拼接SQL,就必须写两个逻辑。
(3)解决过程:连接数据库,获取数据库类型,然后根据类型选择拼接的SQL。
if (itemCount > 0) { DBManager dbMgr = DBManager.getDBManager(); if (dbMgr != null) { try (Connection oConn = dbMgr.getConnection() ) { DatabaseMetaData data = oConn.getMetaData(); String dataName = data.getDatabaseProductName(); //如果总记录数大于0 分页 支持mysql和oracle if (dataName.equalsIgnoreCase("MySql")) { sql = sql + " limit " + pageBean.getStartIndex() + "," + pageBean.getPageSize(); } else if (dataName.equalsIgnoreCase("Oracle")) { sql = "SELECT * FROM (SELECT tabs.*, ROWNUM AS rowno FROM ( " + sql + " ) tabs WHERE ROWNUM <= " + pageBean.getEndIndex() +") table_alias WHERE table_alias.rowno >= "+pageBean.getStartIndex() ; } } catch (Exception e) { throw new RuntimeException(e); } } }四、总结
数据库类型各种各样,开始的时候写的SQL尽量符合SQL标准的。
代码中尽量少的使用拼接SQL。
尽可能熟悉各大主流数据库。
- IOS开发中遇到的各种问题以及解决方案集锦
- 项目管理中遇到的问题以及解决方案(网络转载)
- 《信息安全系统设计基础》实验过程中遇到的问题以及解决方案
- 办公系统中经常遇到的权限管理问题 (一)解决方案
- VS系列+QT5开发遇到的部分问题以及解决方案
- yii2开发遇到的问题以及解决方案
- spring2.5整合ibatis2.3事务管理时遇到的问题以及需要的jar包
- ThinkPHP内容管理系统开发日记(四)-- 配置信息与开发Longin模块以及模板
- 项目中遇到的一些需要重构的问题以及解决方案1-应该尽量减少缩进层次
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- 公司内部管理系统-用YII开发中遇到的问题(更新中...)
- 基于.net core2.1开发遇到的问题记录以及解决方案
- CentOS下Mysql数据库的安装与配置以及遇到的问题及其解决方案
- 重新搭建"灶具维修管理系统"的VB开发环境遇到的几个问题
- IOS开发中遇到的各种问题以及解决方案集锦
- 摘要 MAC,PIN,磁道密钥 在平时的工作中,很少接触安全这块内容,最近需要自己独立完成安全这块内容,在开发中遇到的问题会在下面的理解中得到相应的解决。 在交易平台中,基于安全考
- AngularJs 开发遇到的问题,以及解决方案
- ios系统web(微信公众号)开发遇到的问题及解决方案
- 微信支付开发中遇到的问题以及注意事项和解决方案
- j2ee 使用tomcat开发网站需要访问中文名的资源遇到的问题解决方案。。