数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

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


发布日期:2023年04月12日
 
oracle到mysql的迁移步骤及各种注意事项

最近公司一个项目需要将数据库进行一次迁移从oracle到mysql网上资料甚少现将我本次迁移过程中所遇到的一些问题总结于此(主要是存储过程的迁移)希望能给自己做一个日后的参考如果有幸能帮助到大家更好

mysql中没有包的概念因此迁移的时候将存储过程命名为包名存储过程名的格式

mysql存储过程格式

DELIMITER $$ 分隔符

CREATE PROCEDURE([[IN |OUT ] 参数名 数据类型…]) IN和OUT写在最前面其中IN可以省略

CREATE PROCEDURE `pkg_ypglprc_ypsc`(

prm_ypbm VARCHAR (

OUT prm_AppCode VARCHAR (

程序执行代码

OUT prm_ErrorMsg VARCHAR (

程序执行错误信息

BEGIN

/*变量定义*/

DECLARE n_count DECIMAL () ;

DECLARE done INT(

/*设置游标结束标志*/

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=; 如果NOT FOUND取不到值则将done赋值并且程序继续执行

SET done=;

/*定义一个区块lavel_error逻辑错误处理*/

label_error : BEGIN

/*定义游标*/

DECLARE cur_bdjl CURSOR FOR

SELECT ……

/*打开游标*/

OPEN cur_bdjl ;

REPEAT

FETCH cur_bdjl INTO v_aaz

IF NOT done THEN 如果结束标志done为则继续循环

……

END IF;

/*结束循环关闭游标*/

UNTIL done 直到NOT FOUND

END REPEAT ;

CLOSE cur_bdjl ;

SET prm_AppCode = noerror ; 将prm_AppCode设为正确

SET prm_ErrorMsg = ;

END;

END$$

DELIMITER ;

数据类型

Oracle:varchar Mysql:varchar() (参数自设)

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 { errornumber | { SQLSTATE errorstring } | condition } SQL statement;

SQLWARNING 代表所有以开头的错误代码

NOT FOUND 代表所有以开头的错误代码也包括游标结束的时候

SQLEXCEPTION 代表除了SQLWARNING和NOT FOUND 的所有错误代码

eg DECLARE EXIT HANDLER FORSQLEXCEPTIONSQLWARNINGNOT FOUND SET a = ;

一个begin…end里面只能声明一个HANDLEREXIT表示遇到这种异常时就执行SET a = 然后结束这个存储过程CONTINUE表示遇到这种异常时就SET a = 然后继续执行之后的存储过程

跳转

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_curnameaaz这种写法所以必须将游标取得的所有字段FETCH INTO 到变量里循环

Mysql里有三种循环方式

WHILE循环

WHILE expression DO

statements

END WHILE;

LOOP循环

LOOP

statements

END LOOP;

REPEAT UNTIL循环

REPEAT

statements

UNTIL expression

END REPEAT;

序列

Mysql中没有序列用函数+表的方法取代

建表语句

CREATE TABLE `seq` (

`name` varchar() NOT NULL DEFAULT COMMENT 序列号生成器名称

`val` bigint() unsigned NOT NULL COMMENT 序列号

`increment` int() DEFAULT COMMENT 序列的增量

`min` bigint() DEFAULT NULL COMMENT 序列最小值

`max` bigint() DEFAULT NULL COMMENT 序列最大值

`cycle` char() DEFAULT N COMMENT 是否循环

PRIMARY KEY (`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf COMMENT=mysql模拟序列号生成器用表

函数如下(自己写的可能有错)

DELIMITER $$

DROP FUNCTION IF EXISTS `seq`$$

CREATE FUNCTION `seq`(seq_name VARCHAR())RETURNS BIGINT(

BEGIN

DECLARE v_value BIGINT(

DECLARE v_CYCLE CHAR;

DECLARE v_MIN BIGINT(

DECLARE v_MAX BIGINT(

SELECT avalaMINaMAXaCYCLE INTOv_valuev_MINv_MAXv_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 (ABC) = (SELECT ABC FROM TABLE_ K WHERE KY =TY) WHERE TX = V_X;

Mysql: UPDATE TABLE TTABLE_ K SET TA =KATB=KBTC=KC WHERE KY = TY ANDTX = V_X

GROUP BY:

mysql的group by 语句可以select 没有被分组的字段

select idnameage from A group by age

这个取出的idname所在的行是每个分组中的第一行数据

调用

Mysql: call procedure_name(所有参数)

跳出循环

Oracle: EXIT;

Mysql: 将循环的内容定义为一个区块label_loop需要跳出循环时则 leave label_loop;

注释

#注释内容

注释内容 注意 后需要加一个空格

块注释用/*注释内容*/

表的注释

在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转换为CHAR(参数的值在all_tab_columns的DATA_LENGTH DATA_PRECISION DATA_SCALE中取得

在oracle中执行如下语句注意decode函数里的参数需根据上一步的查询结果转换

select altertable ||atable_name|| modify column ||lumn_name|| ||decode(bdata_typeVARCHARVARCHAR(||bDATA_LENGTH||DATEDATETIMENUMBERDECIMAL(||bDATA_PRECISION||||bDATA_SCALE||CHARCHAR(||bDATA_LENGTH||LONGRAWmediumblob)|| comment ||||comments||||;

from user_col_comments aall_tab_columnsb

where ments is not null

and atable_name = btable_name

and lumn_name = lumn_name

and bowner = YDMIS;

将得到的结果放到mysql中执行即可添加表字段的注释

函数

功能 oracle mysql 备注 egoracle egmysql

连接字符串 || concat() a||b||c concat( abc

将其他格式转换为字符串 concat(x

截取字符串 substr() substring() substr(abcd) substring(abcd

string转换为date to_date() str_to_date(str format) to_date(aaeyyyymmdd hh:mi:ss) str_to_date(aae%Y%m%d %H:%i:%s

获取当前日期 sysdate now()sysdate()current_date now()返回的是程序开始执行时的时间sysdate()返回实时时间

一般用now()

current_date表示当前的年月日

取出日期的指定部分 date_format(datetype) %Y:年

%c:月

%d:日

%H:小时

%i:分钟

%s:秒 date_format(now()%Y%c%d %h:%i:%s

增加一天 sysdate+ DATE_ADD(dateINTERVAL expr type) sysdate+ DATE_ADD(now() INTERVAL DAY)

类型转换 TO_CHAR

TO_DATE

TO_NUMBER cast(xxx as type) type:二进制 : BINARY

字符型可带参数 : CHAR()

日期 : DATE

时间 TIME

日期时间型 : DATETIME

浮点数 : DECIMAL

整数 : SIGNED

无符号整数 : UNSIGNED to_char() cast( as char())

精度转换 to_number(xtype) round(xd) 保留到小数点后d位而第d位的保留方式为四捨五入若要保留x值小数点左边的d位可将d设为负值

替换空值 NVL( string replace_with) ifnull(string replace_with)

decode() decode (expression search_ result_ default) case expression when search_ then result_ else def

               

上一篇:Oracle自动异地远程数据备份研究

下一篇:OracleRMAN物理备份技术之恢复案例三