title: oracle向mysql改造
abbrlink: 23712
date: 2020-1-10 11:44:53
tags:

  • oracle
  • mysql
    categories:
  • oracle
  • mysql

前言

由于工作需要,把oracle数据库改造成mysql数据库,而oracle和mysql在一定程度上有很大的区别,我们的工作是在已有项目改bug,所以特地总结一下这几天项目需要的改动。

1.函数式报错

1.1start with connect by prior函数错误

1.1.1问题描述:

这个是oracle特有的一个函数,是根据条件递归查询"树"。常用用法:start with connect by prior parentId=id或start with connect by prior id=parentId,第一种是:查询结果自己所有的后代节点(包括自己);第二种用法是查询结果自己所有的父类节点(包括自己)。

1.1.2解决方案:

Mysql不支持通过start with connect by进行递归查询,所以创建函数进行查找。

首先是第一种:查询结果自己所有的后代节点(包括自己),首先得了解find_in_set这个函数作用,举个例子:find_in_set(parent_id,”1,2,3”)的意思是parent_id在1,2,3内。创建函数如下:

set global log_bin_trust_function_creators=TRUE;#创建前需要
create function getTaskObjects    #getTaskObject 函数名称
(rootId varchar(100))            #输入值类型
returns varchar(1024)            #返回值类型
BEGINDECLARE sTemp VARCHAR(1024);   #定义变量DECLARE sTempChd VARCHAR(1024);#定义变量SET sTemp = '';-- SET sTempChd = CAST(auth_id AS CHAR);SET sTempChd = rootId;WHILE sTempChd IS NOT NULL DO #如果不空一直循环IF sTemp = '' THENSET sTemp = sTempChd;ELSESET sTemp= CONCAT(sTemp,',',sTempChd);END IF;SELECT GROUP_CONCAT(dept_id) INTO sTempChd FROM sys_dept WHERE FIND_IN_SET(parent_id,sTempChd)>0;#把所有的id拼接接起来END WHILE;#结束循环RETURN sTemp; #返回结果
END

调用可以向平时调用内置函数一样调用,以下面这张表为例,这是全部数据。

两个查找和与之对应结果:

select getTaskObjects('101')
select * from sys_dept  WHERE find_in_set(dept_id,getTaskObjects('101'))>0



      第二种:查询结果自己所有的父类节点,返回值也是所有符合条件id拼接起来字符串,所以我们调用也得加find_in_set(id,getTaskObject(子节点id))

create function getTaskObjects2    #getTaskObject 函数名称
(rootId varchar(100))            #输入值类型
returns varchar(1024)            #返回值类型
BEGIN DECLARE sTemp VARCHAR(100); #定义变量DECLARE sTempChd VARCHAR(100);#定义变量DECLARE allData VARCHAR(1024);#定义变量SET allData='';             SET sTempChd =rootId;SET sTemp='';WHILE sTempChd !=0 DO #如果不空一直循环SET sTemp=sTempChd;SET allData=CONCAT(allData,',',sTempChd);SELECT PARENT_ID INTO sTempChd FROM sys_dept where dept_id=sTemp;END WHILE;  #结束循环RETURN allData;     #返回结果END

一样以下面这张表为例,这是全部数据。

两个查找和与之对应结果:

select getTaskObjects2('101')
select * from sys_dept  WHERE find_in_set(dept_id,getTaskObjects2('101'))>0


1.1.3 延伸:

1.1.3.1 传入的table为动态table表怎么办?

本以为这样写就可以全部用上,但这个有个明显的不足就是table只能写死,一开始的想法是把table传进去,但报错了,我是这样写的:

Select parent_id into sTempChd from tableName(ps:这是个变量) where object_id=sTemp;

会报tableName这个表不存在的错误,因为sql不会自动识别tableName这个变量,它会认为有这个tableName的表 。

网上查找了资料说可以用动态sql,但函数不支持动态sql,所以解决办法就是写一个存储过程,以下讲解的是第二种查询结果自己所有的父类节点,如下:

CREATE PROCEDURE SELECT_TREE(IN keyColumn VARCHAR(32) CHARSET utf8,IN tableName VARCHAR(32) CHARSET utf8,IN parentColumn VARCHAR(32) CHARSET utf8,
IN keyValue VARCHAR(64) CHARSET utf8,OUT returndata VARCHAR(2048) CHARSET utf8)--输入输出参数,in为输入,out为输出BEGINdeclare sTemp VARCHAR(100); --定义变量SET sTemp = keyValue;SET returndata='';WHILE sTemp IS NOT NULL DO--如果不空一直循环-- 创建sqlSET @selectSql = CONCAT('select ',parentColumn,' INTO @recordcount  from ',tableName,' where ',keyColumn,"='",sTemp,"'");-- 执行动态生成的sql语句PREPARE temp FROM @selectSql;EXECUTE temp;SET sTemp = @recordcount;--其实对比上面仔细看可以看出只是这一步不同IF sTemp IS NOT NULL THENSET returndata=CONCAT(returndata,',',sTemp);END IF;END WHILE; --结束循环END

可以对比上面的自定义函数,一个注意地方是@recordcount 代替sTempChd 变量,声明这是个变量,其他是语法问题,逻辑和自定义函数相同。

然后就是调用测试,我是在Navicat测试的,我的版本可以直接传参(听说低版本不可以直接测试)。注意的是out输出参数要传递变量,如:(keycolum,tableName,pid,in,@returnData)。以项目中一张表为例:

call SELECT_TREE('package_id','usbp_object_package','parent_id','74',@returnData);
SELECT @returnData

运行结果:

以上是在Navicat调用的,在项目中,我们需要写sql调用,用的是mybatis框架,调用如下,最重要是要加上statementType=”CALLABLE”,如果传入是map,returnData这个名字可以随便取,传入是pojo,这个值必须固定,在pojo里面应该有个同名变量。返回值去传入的参数里拿,这个我传入的是map,所以直接去传入的map拿了,至于传入pojo要给个变量returnData,会自动注入。

<mapper namespace="com.shd.biz.Tree.service.impl.TreeServiceImpl"><!-- 注意 statementType="CALLABLE" --><select id="treeParent" statementType="CALLABLE">{call SELECT_TREE(#{keyColumn,mode=IN},#{tableName,mode=IN},#{parentColumn,mode=IN},#{keyValue,mode=IN},#{returnData,mode=OUT,jdbcType=VARCHAR})}</select>
</mapper>

Map<String, Object> parameters=new HashMap<String, Object>();parameters.put("keyValue", value);parameters.put("tableName", table);parameters.put("keyColumn", keyColumn);parameters.put("parentColumn", parentColumn);this.getDao().queryForDataSet(SQL_PRIFIX + "treeParent", parameters);//结果是从传入参数里面拿,不是从返回结果拿String returnData = parameters.get("returnData").toString();
1.1.3.2 调用报方法read-Only错误

最后还有个报错是事务报错,是因为我项目get开头的方法设置了readOnly=“true”,而调用存储过程如果还设置readOnly属性就会报错,要加上@Transactional(readOnly = false)或改变service方法名。

1.2 Sysdate报错

解决Sysdate替换为sysdate()

1.3 to_char报错

网上查找的资料:

date_format(date,’%Y-%m-%d’) -------------->oracle中的to_char();

str_to_date(date,’%Y-%m-%d’) -------------->oracle中的to_date();

具体还得看链接

1.4 日期的计算

oracle 可以直接用sysdate加减乘除,而mysql不可以,如

近一个月:

​       Oracle-------->sysdate-29//日期,今天减去29天

​        Mysql--------->

<if test="REPORT_TIME == '本周'">and YEARWEEK(date_format(report_time,'%Y-%m-%d')) = YEARWEEK(now()) </if><if test="REPORT_TIME == '本月'">and report_time >=DATE_ADD(curdate(),interval -day(curdate())+1 day) and report_time &lt;= last_day(SYSDATE())</if><if test="REPORT_TIME == '近1个月'">and report_time BETWEEN date_sub(SYSDATE(),interval 1 month) AND SYSDATE()</if><if test="REPORT_TIME == '近3个月'">and report_time BETWEEN date_sub(SYSDATE(),interval 3 month) AND SYSDATE()</if><if test="REPORT_TIME == '近1年'">and report_time BETWEEN date_sub(SYSDATE(),interval 12 month) AND SYSDATE()</if>

1.5 Rownum报错

在mysql中没有Rownum,所以要特殊的实现方法,实现和效果如下,但我项目是用来分页,所以直接就用limit。

SELECT @rownum:=@rownum+1 AS rownum, table .*
FROM (SELECT @rownum:=0) r, table ;

1.6 ||运算符报错

Mysql中||表示或的意识,而Oracle中||运算符可以将两个或两个以上的字符串连接在一起,在mysql中用concat代替。

2 其他报错

2.1 表别名报错

别名报错,首先mysql不可以像Oracle一样直接多重查找不加别名,如:

Select key from(select key from database);改为Select t.key from(select key from database) t;

但在删除时又不可以加别名,如 :

Delete from database r where r.id=?会报错,得改为:Delete from database where id=?

2.2 Mysql没有序列问题

重新解决的办法几个,一个是用uid,另外一个也是根据自定义函数等进行创建一个伪序列,具体创建有一篇博客已经详细介绍了,
具体链接

2.3 存储类型bigInteger装换toBigDecimal

原来oracle存储数据类型是integer,现在存储类型为decimal,启动时报错,bigInteger cannot to cast toBigDecimal,所以,就得装换一下。

这是详情

2.4 union报错

Oracle的union和mysql的union的一个细节错误导致,oracle可以用括号括起来,而mysql不可以

Oracle向mysql改造相关推荐

  1. 去O入云的探索--Oracle到MySQL的迁移改造方案

    ,点击上方"蓝字" 关注我们,享更多干货! 1.表结构改造 数据类型映射关系 字段映射关系请参考: https://blog.csdn.net/weixin_34128839/ar ...

  2. 从Oracle到MySQL,余额宝云实践分享

    余额宝.百度百发.腾讯财付通谋划的互联网理财工具,吹响了互联网对金融行业的进军节奏.而后,网易.和讯.京东商城.苏宁云商等二线实力企业纷纷涉水.另一边,一众金融精英也在频频转换思路,不仅银行网络中心从 ...

  3. 全栈溯源、mAPM、金融性能、Oracle VS. MySQL:看APM技术专场有哪些干货

    在日益复杂的应用环境中,网络.移动端.浏览器端.服务端的性能问题种类繁多,如何精准的定位问题根源,并留住用户是关键问题.尤其是云计算平台的普及使用,更是对应用性能的追踪和优化提出了新的拷问.在此前提下 ...

  4. 开始构建你的DBaaS:使用zCloud自动化安装部署Oracle和MySQL数据库

    更多精彩,请点击上方蓝字关注我们! 云和恩墨自研的zCloud是目前业内对商业数据库(Oracle)及开源数据库(MySQL.Redis.PostgreSQL)支持都十分完善的数据库云管平台,可以应对 ...

  5. 从Oracle到MySQL,余额宝的云实践

    从Oracle到MySQL,余额宝云实践分享 http://www.csdn.net/article/2013-11-07/2817426-interview-financial-case-yuerb ...

  6. 从Oracle到MySQL,余额宝云实践分享 20131111(转)

    摘要:囿于安全性.合规性和风险等方面的挑战,即使海外,金融业也从未真正将业务迁往公有云.无可奈何之下,余额宝"背水一战",却发现胜利的果实是如此甜美.更有价值的是,揭开了技术变革的 ...

  7. 亿级数据迁移 从Oracle到Mysql

    一. 背景   基于成本和数据安全的考虑,需要将XX的存储数据源从Oracle切成MySQL.券系统作为XX中心最底层系统,不仅数据极其重要而且数据量庞大,如何设计一套完整迁移方案保证准确无误的实现数 ...

  8. Mybatis中Oracle和Mysql的Count字段问题

    Mybatis中Oracle和Mysql的Count字段问题 我们在进行项目开发时经常会碰到查询总数的问题,所以我们直接是用select count(1) from table来进行查询.那么在Myb ...

  9. oracle收购Mysql后,Mysql的安装配置方法

    自从Oracle收购MySQL后,略微发生了一些小小的变化,原来mysql安装完成后默认是没有密码的,但是新版的mysql安装完成后oracle提供了一个free password放着/root/.m ...

最新文章

  1. AutoML自动化机器学习技术深入
  2. 3D物体识别的如果检验
  3. android service alertdialog,Android service里面启动alertdialog
  4. 链表归并成递减c语言,将两个递增的单链表合并为一个递减的单链表
  5. java对象转JSON JS取JSON数据
  6. jpa 定义中间表实体_JPA系列之-带你快速掌握JPA
  7. c++语言怎么实现字符串拼接,C++ string类和字符串的访问和拼接操作
  8. 光电转换模块_针对100G QSFP28 SR4光模块的特征及工作原理进行分析
  9. 性能评测|影驰RTX4090金属大师系列显卡正式发售!
  10. 遥感中的数字量化值DN, 辐射亮度Radiance, 反射率Reflectance,发射率Emissive的意义
  11. excel打开很慢_从海量Excel文件中快速高效地提取数据
  12. 一文读懂Hoo Smart Chain的可视化公链
  13. 知名互联网公司面试题
  14. NLP比赛-小布助手对话短文本语义匹配
  15. 三款主流数码绘画软件调研分析
  16. namedtuple使用
  17. 两组字符串去重/两个列表去重
  18. 水库水雨情监测系统方案分享-水库水位监测-水情监测
  19. 利用Python进行性能测试(上)
  20. 【Linux 内核 内存管理】memblock 分配器 ③ ( memblock_region 内存块区域 | memblock_region 结构体成员分析 | memblock 分配器标志位 )

热门文章

  1. C# wpf 实现Canvas内控件拖动
  2. 2021年全球硫酸镍收入大约2184.2百万美元,预计2028年达到2715.2百万美元
  3. 关于Linux系统指令 top 之 %wa 占用高,用`iostat`探个究竟
  4. 安卓老版本游戏/七八年前安卓游戏通过安卓虚拟机实现兼容
  5. 部署 Exsi 7.0.3
  6. 新工科建设形势下的计算机类专业人才培养方案
  7. m_map包 绘制世界地图并投点(matlab)
  8. GDI泄漏问题:QWindowsBackingStore::flush:GetDC failed
  9. Linux文件、目录的权限
  10. 转载:rose软件下载(Rational Rose 2003 Enterprise Edition)