一、前言

  公司本来的项目是基于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下一样好。
(责任编辑:一刀劈破天)