当前位置:数据库 > Oracle >>

oracle到mysql的迁移步骤及各种注意事项

oracle到mysql的迁移步骤及各种注意事项
 
最近公司一个项目需要将数据库进行一次迁移,从oracle到mysql,网上资料甚少,现将我本次迁移过程中所遇到的一些问题总结于此(主要是存储过程的迁移),希望能给自己做一个日后的参考,如果有幸能帮助到大家更好。
-- mysql中没有包的概念,因此迁移的时候将存储过程命名为'包名.存储过程名'的格式
mysql存储过程格式:
DELIMITER $$   -- 分隔符
-- CREATE PROCEDURE([[IN |OUT ] 参数名 数据类型...]) ,IN和OUT写在最前面,其中IN可以省略
CREATE PROCEDURE `pkg_ypgl.prc_ypsc`(
 prm_ypbm VARCHAR (20),  
  OUT prm_AppCode VARCHAR (20),
  -- 程序执行代码
  OUT prm_ErrorMsg VARCHAR (100)
  -- 程序执行错误信息
)
BEGIN
  /*变量定义*/
  DECLARE n_count DECIMAL (8) ;
 DECLARE done INT(10);
 
  /*设置游标结束标志*/
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;  -- 如果NOT FOUND,取不到值,则将done赋值1,并且程序继续执行
SET done=0;
 
/*定义一个区块lavel_error,逻辑错误处理*/
   label_error :  BEGIN
  /*定义游标*/
 DECLARE cur_bdjl CURSOR FOR
  SELECT .....
   /*打开游标*/
   OPEN cur_bdjl ;
   REPEAT
     FETCH cur_bdjl INTO v_aaz001....
IF NOT done THEN -- 如果结束标志done为0则继续循环
........
END IF;
   /*结束循环,关闭游标*/ 
     UNTIL done -- 直到NOT FOUND
   END REPEAT ;
   CLOSE cur_bdjl ;
   
   SET prm_AppCode = 'noerror' ;  -- 将prm_AppCode设为正确
   SET prm_ErrorMsg = '' ;
  END;
 
  END$$
DELIMITER ;
 
数据类型:
Oracle:varchar2    Mysql:varchar(20)  (参数自设)
Oracle:number()    Mysql:decimal()
Oracle:date       Mysql:datetime
 
定义变量:
Mysql需要在每句前面加DECLARE
 
给变量赋值:
Oracle:v_string := ‘asdas’;    Mysql: SET string := ‘asdas’; (等号前面的冒号可以有也可以没有)
 
异常处理:
Oracle:EXCEPTION WHEN OTHERS THEN….
Mysql: DECLARE { EXIT | CONTINUE } HANDLERFOR { error-number | { SQLSTATE error-string } | condition } SQL statement;
   SQLWARNING 代表所有以01开头的错误代码 
   NOT FOUND 代表所有以02开头的错误代码,也包括游标结束的时候
   SQLEXCEPTION 代表除了SQLWARNING和NOT FOUND 的所有错误代码
eg. DECLARE EXIT HANDLER FORSQLEXCEPTION,SQLWARNING,NOT FOUND SET a = 1;
注:一个begin....end里面只能声明一个HANDLER,EXIT表示遇到这种异常时就执行SET a = 1然后结束这个存储过程,CONTINUE表示遇到这种异常时就SET a = 1,然后继续执行之后的存储过程
 
跳转:
Oracle:  GOTO label_error;
            …..
<<label_error >>
Mysql:初始化错误代码prm_AppCode为“错误”,定义一个区块label_error,在区块的最后将prm_AppCode set为’noerror’,中间触发条件,将GOTO label_error;改写成leave label_error;跳出区块
 
 
游标:
Mysql只有静态游标,没有动态游标,用存储过程代替
定义游标的语句为DECLAREcur_bdjl CURSOR FOR …..
Mysql不支持rec_curname.aaz001这种写法,所以必须将游标取得的所有字段FETCH INTO 到变量里
 
 
循环:
Mysql里有三种循环方式
(1).WHILE循环
 WHILE  expression DO
 statements
 END   WHILE;
 (2).LOOP循环
 LOOP
  statements
  END  LOOP;
 (3).REPEAT UNTIL循环
 REPEAT
 statements
 UNTIL expression
 END  REPEAT;
 
 
序列:
Mysql中没有序列,用函数+表的方法取代.
建表语句:
CREATE TABLE `seq` (
  `name` varchar(20) NOT NULL DEFAULT '' COMMENT '序列号生成器名称',
  `val` bigint(20) unsigned NOT NULL COMMENT '序列号',
  `increment` int(4) DEFAULT '1' COMMENT '序列的增量',
  `min` bigint(20) DEFAULT NULL COMMENT '序列最小值',
  `max` bigint(20) DEFAULT NULL COMMENT '序列最大值',
  `cycle` char(1) DEFAULT 'N' COMMENT '是否循环',
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mysql模拟序列号生成器用表'
 
函数如下(自己写的,可能有错):
DELIMITER $$
DROP FUNCTION IF EXISTS `seq`$$
CREATE FUNCTION `seq`(seq_name VARCHAR(20))RETURNS BIGINT(20)
BEGIN
DECLARE v_value BIGINT(20);
DECLARE v_CYCLE CHAR;
DECLARE v_MIN BIGINT(20);
DECLARE v_MAX BIGINT(20);
SELECT a.val,a.MIN,a.MAX,a.CYCLE INTOv_value,v_MIN,v_MAX,v_CYCLE FROM seq a WHERE NAME = seq_name;
   IFv_CYCLE = 'Y' AND v_value = v_MAX THEN -- 该序列为循环且当前值为其最大值
  UPDATE seq  -- 将当前值设为 v_MIN  
  SET   val = v_MIN  
  WHERE NAME = seq_name; 
 ELSE
  UPDATE seq  -- 否则将当前值设为val + increment  
  SET   val = val + increment  
  WHERE NAME = seq_name;
  END IF;
  SELECT  val INTO v_value FROM seqWHERE NAME = seq_name;
   RETURN v_value;
END$$
DELIMITER ;
 
 
 
 
更新:
Oracle: UPDATE TABLE T SET (A,B,C) = (SELECT A,B,C FROM TABLE_2 K WHERE K.Y =T.Y) WHERE T.X = V_X;
Mysql: UPDATE TABLE T,TABLE_2 K SET T.A =K.A,T.B=K.B,T.C=K.C WHERE  K.Y = T.Y ANDT.X = V_X
 
GROUP BY:
mysql的group by 语句可以select 没有被分组的字段,如
select id,name,age from A group by age
这个取出的id,name所在的行是每个分组中的第一行数据
 
调用:
Mysql: call procedure_name(所有参数);
 
 
跳出循环:
Oracle: EXIT;
Mysql: 将循环的内容定义为一个区块label_loop,需要跳出循环时则 leave label_loop;
 
 
注释:
1、#注释内容
2、-- 注释内容  注意-- 后需要加一个空格
3、块注释用/*注释内容*/
 
 
表的注释:
在oracle中执行如下语句:
select 'altertable '||table_name||' comment'||' '''||COMMENTS||' '''||';' fromUSER_TAB_COMMENTS where comments is not null;
将得到的结果放到mysql中执行即可添加表名的注释
 
 
表的字段注释:
在oracle中执行如下语句:
select distinct(data_type)  FROM all_tab_columns where owner= 'YDMIS'
将查询出的本次转换涉及到的数据类型用decode函数转换为Mysql中对应函数(参数)的形式,如将CHAR转换为C
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,