您的位置:首页 > 数据库 > Oracle

以MySQL数据库开发的内容管理系统,需要兼容Oracle数据库遇到的问题以及解决方案。

2018-06-19 16:43 791 查看

一、问题背景描述

开发的系统默认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。

尽可能熟悉各大主流数据库。


阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐