如何将oracle数据库转换成mysql数据库,现在公司有急用,方法可用的话再加分!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将oracle数据库转换成mysql数据库,现在公司有急用,方法可用的话再加分!相关的知识,希望对你有一定的参考价值。

讲解Oracle数据库移植到mysql
出处:IT专家网 日期:2010-06-24

一、前言

公司原来的项目是基于Oracle数据库的,Oracle功能强大,但是部署和管理较复杂,更重要的是,购买Oracle的费用不是每个客户都愿意承担的。因此,迫切需要把公司项目所用数据库移植到一个简单好用的数据库上。当然,如您所料,我们选择了广受欢迎的MySQL。

作为一个开源数据库,MySQL用无数案例证明了她的可用性,因此让我们把重点放在如何将Oracle移植到MySQL上。已经有很多的文章和专题介绍了Oracle移植到MySQL的方法和步骤,也有相当多的工具可以辅助这种移植过程。但是,由于数据库实现的差异,完美的移植工具是不存在的,移植过程中不断碰到的问题证明了这一点,特别是您使用了Oracle的一些高级特性时。

从Oracle移植到MySQL主要有六个方面的内容需要移植,一是表Table,包括表结构和数据,二是触发器Trigger,三是存储过程Procedure,函数function和包Package,四是任务Job,五是用户等其他方面的移植,六是具体应用程序通过SQL语句访问时的细节差异克服。

笔者用来移植测试的数据库是:Oracle 9i ,MySQL 6.0,Windows 2000环境。

二、表的移植

这个部分的移植是最容易用工具实现的部分,因为很多MySQL的图形管理工具都自带这样的移植工具,比如SQLYog,MySQL Administrator等。但是,这些工具的移植能力各有不同,对字段类型转换、字符集等问题都有自己的处理方式,使用时请注意。

笔者使用“SQLYog Migration Toolkit”工具按提示步骤移植后,表的主要结构和数据将成功移植,主要包括表的字段类型(经过映射转换,比如number会转换为double,date转换为timestamp等,请小心处理日期字段的默认值等),表的主键,表的索引(Oracle的位图索引会被转成BTree索引,另外表和字段的注释会丢失)等信息。需要特别注意的是,Oracle的自增字段的处理。

大家知道,Oracle通常使用序列sequence配合触发器实现自增字段,但是MySQL和SQL Server等一样,不提供序列,而直接提供字段自增属性。所以,请把Oracle里面的自增字段实现直接改为MySQL的字段属性,而且,这个字段必须是主键(key)并且不能有默认值。

还有一个问题,如果您的应用要直接使用Oracle的某个序列,那么您只能在MySQL里面模拟实现一个,具体方法就是利用MySQL的自增字段实现的。

三、触发器的移植

首先,MySQL在6.0以后才支持触发器!

触发器的移植没有现成工具,因为两者之间的语法差异较大,您只能通过手工对照着原来的逻辑一个一个添加。

这里要说明一下,MySQL的SQL过程语法和Oracle PL/SQL大致相同,但还是有些细微差别:

1. 变量声明Declare部分,在Oracle中Declare语句位于Begin之前,在MySQl中,Declare位于Begin之后;

2. 注释不同,在Oracle中,可用 “—“ 注释一行或“/* */”注释一段,在MySQL中,需用 “/* */”或“#”来注释

3. 对触发前后变量值的引用方法不同;在Oracle中,用 :new.eid, :old.eid表示新旧值,

在MySQL中,用 New.eid,old.eid表示新旧值

4. 移植中发现的问题

1) Oracle的自治事务autonomous_transaction ,MySQL不支持,您必须用其他方式实现,MySQL不允许在触发器过程中执行对触发器所在表的操作(包括读写)

2) MySQL函数和trigger中不能执行动态SQL语句,也就是说,您不能在触发器里面组合出来一个SQL字符串,然后用exec来执行

3) Oracle的表级触发器,MySQL还不支持,所以必须改成使用行级触发器,注意这会导致有时SQL语句的执行效率很低

四、存储过程,函数和程序包的移植

程序包是Oracle用来组织逻辑功能的一个Object,MySQL不支持,因此需要将包里的存储过程、函数等全部放到该数据库公有过程和函数里面。

MySQL的过程和函数语法与Oracle类似,但还是有细微差别,除了数据类型需要转换,还有:

1. 格式不同,例如:

Oracle为:

CREATE OR REPLACE procedure procedure1(TableName in varchar2) is

MySQL应该为:

CREATE procedure procedure1( in TableName varchar(200))

2. 赋值语句不同:

Oracle赋值语句为:

strSQL := ‘update table set field1=1’;

MySQL应该为:

Set StrSQL = ‘update table set field1=1’;(用:=也行)

3. 一些要用到游标的过程请注意

MySQL过程不支持嵌套游标,不支持带参游标,不支持记录类型%ROWTYPE,不支持数组等,原Oracle用到这些的必须改写

五、Job的移植

Job是Oracle的定时任务实现的方法,MySQL6中用Event实现,具体语法请参考MySQL手册。

在MySQL中使用event请注意,默认它是不运行的,您可以

1) 保证MySQL定时任务event scheduler运行,需要MySql 5.1.6以上,并且在启动后执行SET GLOBAL event_scheduler = ON;(也可以在初始配置文件比如my.ini中加入event_scheduler = ON的参数)

2) 启用event功能后,每次执行会往MySQL的错误日志文件写一些信息(data目录下的“主机名.err”文件),导致这个文件越来越大(除非经常做flush log操作)。所以,如果您的event执行很频繁,可在my.ini中加参数console=TRUE,这样执行event的信息就不会写进来了
六、用户的移植

Oracle的用户管理和MySQL下有较大区别,请分别建立用户,并赋予合适的权限。

七、应用程序的移植

由于语法细节上的差异,导致很多SQL语句需要改写。笔者记下了所有移植过程中碰到的SQL语句细节差异,这些也是一般项目可能会用到的地方,虽然肯定不全,但也列出来以供参考:

1)Oracle的to_char函数不能再使用,换用如CONCAT(14.3)的形式,为了提高应用程序兼容性,建议手工写一个

2)Oracle的to_date函数不能再使用,建议手工写一个添加到MySQL数据库

3)Oracle的decode函数不能再使用,换用SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END 的形式

4)nvl这样的一些专用函数,MySQL是没有的,可以把

select nvl(to_char(num),'nothing') from t_equipment转换成

select case num when num then num else 'nothing' end from t_equipment

5)instr之类的函数,函数名相同,但参数个数不同

6)Oracle的sysdate要写成sysdate()的形式

7)包的形式已经取消,所以原来以包的方式调用的过程如xx_pack.xxx要写成xxx()

8)带进制字符转数字

Oracle风格:TO_NUMBER(strTmp,'XX') TO_NUMBER(’9’)

MySQL风格:CONV(strTmp,16,10) CONV(’9’,10,10) 如果字符串前后有加减操作,会隐含转换成数字

9) 不能再有直接调用序列的形式,如果一定需要,可以模拟实现一个

10)日期直接加减的含义不同了,比如Oracle中sysdate + 1 变成了sysdate() + interval 1 day(注意如果写成sysdate() + 1 语法还是正确的,但含义是错误的)

查询select sysdate() + 1 from dual 在MySQL得到比如 20080223153234(= 20080223153233 + 1)的数

而在Oracle中会得到第二天当前时刻。

11) MySQL单纯的date类型只是日期不带时间,DATETIME或TIMESTAMP带有时间,用DATE_FORMAT函数可以控制显示形式

12)select 'abc' || 'd' from dual 两个数据执行的结果不同(语法都能通过),MySQL要写成select concat('abc' , 'd')的形式

13) Oracle高级功能,如带有暗示索引的select语句,MySQL是不支持的(语法可以通过)
14)有些MySQL的保留字不能直接用在SQL语句里,要加表名或别名限制,如select RIGHT FROM XX要改成select a.RIGHT FROM XX a

15) Oracle的子查询可以不起别名,但MySQL是必须的,比如下面的别名aa:

select field1 from (select sysdate() as field1 from dual) as aa

16)很多系统表名都是不同的,比如,列出某个表的信息:

select * from tab where TName='T_TEST'改成

select table_name,table_type from information_schema.tables where table_schema = 'user' and table_name=' T_TEST '

17)MySQL下update时不能有本身的子查询

update T_TEST set Flag = 0 where field1 in

(select distinct b.field1 from T_TEST b where b.flag=1)

18)Oracle下’’和null等价,而MySQL则不然

select 1 from dual where '' is null在Oracle下可以取到记录,在MySQL下不能

dual表的使用,substr、trim等函数的主要使用方式和Oracle类似

八、小结和建议

看起来,Oracle移植到MySQL似乎挺麻烦,有没有一键完成的简单办法?呵呵,我没有找到,除非您只使用基本表,只使用基本SQL语句访问它。当然,建议大家初始设计的时侯,就考虑到多数据库的支持,权衡一下使用一些高级功能带来的好处和对可移植性方面带来的损害,这会大大减少后期移植时面对的问题;另外,在应用架构设计时,也建议使用较好的框架去屏蔽这些差异,比如J2EE的Hibernate框架等。

感谢伟大的Oracle,给我们提供了很多的高级功能,有很多是MySQL没有的,因此,在移植时你不得不放弃一些非必须的功能,比如,全表cache、物化视图、函数索引等;如果该功能是必须的,您可能要使用别的方式来实现,或者转到应用程序层面来考虑。当然,这些功能MySQL今天没有,不代表明天也没有,我们可以拭目以待。

由于开源软件的原因,MySQL的bug或者缺陷有时还会干扰你,请仔细测试和优化您的应用程序,调整MySQL的配置参数,确保它可以运行得和Oracle下一样好。

(责任编辑:王倩)
参考技术A 建议使用PowerDesigner将ORACLE转换为物理模型,再转换为逻辑模型,然后通过这个逻辑模型重新选择DBMS(MYSQL),将其转换为MYSQL的物理逻辑模型,在物理逻辑模型上更新触发器,过程等对象,然后生成MYSQL的物理文件,或直接导入到MYSQL数据库实例中。追问

我已经通过powerdesigner将数据库的表结构转换成功了,但是数据没有导入啊!你有什么好的方法能从oracle中将大量的数据导出到mysql中吗?

追答

1.如果每个表的数据量大于100K条的话,通过ORACLE的异构数据库代理建立基于ODBC数据源的异构数据库通道,如果你没有修改过表的字段,就用N个INSERT INTO命令将ORACLE数据库的数据插入到MYSQL中就OK了,如果插入过程中报错,注意数据的类型,必要时在MYSQL中建立中间表,将数据都统一成字符型数据插入中间表,然后再MYSQL中处理。
关于ORACLE异构数据库通道的建立,你可以在网上搜索一下很多。ORACLE的异构数据库访问可以基于ODBC和transparent getway(透明网关)这两种,建议用ODBC的,很好建立(透明网关我现在都没搞好,不知道是什么问题。。。)。
2.数据量小的话可以通过PL/SQL DEVELOPER将数据导成平面文件,然后导入MYSQL(本人没用过MYSQL,所以可行性不清楚,但既然都是比较主流的关系数据库,我想应该可以吧)。
3.通过MSSQL的导入导出工具将ORACLE的数据导进MSSQL数据库中(即将MSSQL数据库看成一个过度数据库或表),再将MSSQL中的数据导入MYSQL,在转换过程中注意数据的类型。
4.在不同的数据库导入导出数据时都要注意数据的类型的选择,如:mssql和oracle之间的数据类型:int(float)/number,varchar/varchar2,date/date,datetime/timestamp等。

本回答被提问者采纳
参考技术B 还简单些啊 对应的数据类型转换 比如 number转成int 序列变成 auto identity 什么primary key啊 自己去看下mysql的例子就清楚了嘛追问

数据库中有非常多的表,难道我要一个一个地去修改吗,现在表结构已经转换成功了,就剩下数据了,希望你能帮到我!

追答

你可以试下CrazyHerozk 所说的

怎么将oracle的sql文件转换成mysql的sql文件

您好,首先需要这两个软件:PowerDesigner软件,oracle数据库。 1、将要导入的库的所有表的表结构(不要表数据,只要表结构)导出成一个.sql文件。 2、在PowerDesinger里找到 File -->> Reverse Engineer --->> Database 参考技术A 转换一般会遇到的问题:
1 、 大小写敏感的区别( 如果服务器 OS 是linux) 。
在oracle 中一般情况下不区分大小写。有时候我们在使用oracle 不注意大小写的问题,表名和字段名不加双引号是不区分大小写的,像这样:insert into tableName 和 insert into TABLENAME 效果是一样的,用工具导出创建/ 数据初始化脚本,得到的结果一般表名和字段名转化成了大写。
但在MySQL 中,所使用操作系统 的大小写敏感性决定了数据库名和表名的大小写敏感性。数据库对应数据目录中的目录,数据库中的每个表至少对应数据库目录中的一个文件( 也可能是多个,取决于存储引擎) 。因此,使用数据库或表实际上是操纵这些文件( 夹) ,所以使用操作系统的大小写敏感性决定了数据库名和表名的大小写敏感性。在以linux 为内核的操作系统中是大小写敏感的。
解决的办法是把mysql 的数据库名和oracle 的大小写保持一致,表名与应用程序中sql 字符串中的表名保持一致,如果应用程序中字段名用了双引号,那请把sql 中的字段名大小写与双引号里的字符保持一致。如果你的应用程序所引用的表名、字段没有统一大小写,那麻烦就大了。
2 、保留字的区别。
像sql 语言的函数名( 如:inteval ,show) 等是保留字。Oracle 中保留字是可以作为表名和字段名,并且不影响使用,但mysql 中保留字是不能作为表名和字段名,如果使用会报语法错误。
解决办法,把sql 语句中的保留字用‘`’ 符号引起来,这个符号位于键盘 的tab 键上面; 如果是字段名还有另外一种方法tablename. 字段名。像这样:insert into tablename (id, `interval`) value(….. 或insert into tablename (id, tablename.inteval) value(….. 。
3 、数据类型的区别。
在mysql 中没有像oracle 中的varchar2 、number ,mysql 有与之对应的varchar 、numeric ,当然在oracle中没有mysql 的time 类型。
解决办法是替换。
4 、自动增长类型的区别。
Oracle 有sequence ,mysql 中没有,但有auto_increment 属性。
解决办法是把Oracle 中sequence 转换成使用auto_increment 属性,某些情况可能还有一种办法可以解决问题,新建一个独立的表用来专门记录自动增长型的数据。
5 、索引长度限制的区别。
从MySQL 4.1.2 开始,MyISAM 和InnoDB 表索引长度支持1000 字节,也就是说索引字段的长度不能超过1000 字节,如果超过会报错:ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes 。如果是UTF-8 编码,相当于333 个字符的长度( 因为UTF8 一个字符占3 个字节) 。Oracle 的索引长度限制比mysql 要宽松得多。解决办法要么改索引的定义,要么改字段的定义长度。
6、SQL中函数名称不一致
可以在网上找oracle 常用函数 与mysql 的对照表,然后逐一修改。网上也可以找到简单的转换工具,效果自己判断。本回答被提问者采纳

以上是关于如何将oracle数据库转换成mysql数据库,现在公司有急用,方法可用的话再加分!的主要内容,如果未能解决你的问题,请参考以下文章

mysql如何把16进制转换成中文字符显示

ORACLE 数据库中在将date类型转换成varchar类型时出现问题。SQL如下:

ORACLE——将多行文本数据转换成一行

sql语句里怎么将String转换成Date

mysql数据库与oracle数据库的切换

在sql中如何将字符串数字转换成数字?