qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          Oracle數據庫移植到MySQL實戰

          項目做好了,更高的要求被提出來,比如,要多數據庫支持,怎么辦?移植!有沒有人做過這事,我好參考一下?哦,這有一個…
            關鍵詞:Oracle MySQL 移植
            一、前言
            公司原來的項目是基于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要寫成selectconcat('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下一樣好。

          posted on 2013-11-08 14:11 順其自然EVO 閱讀(218) 評論(0)  編輯  收藏 所屬分類: 數據庫

          <2013年11月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 潞城市| 韶关市| 昌都县| 赫章县| 城市| 太康县| 龙口市| 青海省| 大荔县| 界首市| 新化县| 巩义市| 元谋县| 波密县| 宁夏| 晋江市| 大姚县| 德钦县| 额敏县| 甘孜| 丹棱县| 台南县| 汽车| 海伦市| 朔州市| 伊通| 峨眉山市| 南安市| 安国市| 开江县| 全椒县| 敦煌市| 安多县| 长治市| 慈利县| 周至县| 梨树县| 长汀县| 桂阳县| 新巴尔虎左旗| 轮台县|