熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

oracle到mysql的遷移步驟及各種注意事項

2013-11-13 15:38:17  來源: Oracle 

  最近公司一個項目需要將數據庫進行一次遷移從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


From:http://tw.wingwit.com/Article/program/Oracle/201311/17055.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.