這幾天把項目的存儲過程從oracle遷移到了達夢8,記錄一下心得。國產資料庫做到這樣,已經算很了不起了,跟oracle相容性確實很高。 但還是有一些細節沒做好,主要是出錯提示不友好,另外一個網上的資料也很少,出問題不好定位。(達夢的錯誤碼比較簡單,就是一個負數,不像oracle是ora 錯誤碼,在百 ...
這幾天把項目的存儲過程從oracle遷移到了達夢8,記錄一下心得。國產資料庫做到這樣,已經算很了不起了,跟oracle相容性確實很高。
但還是有一些細節沒做好,主要是出錯提示不友好,另外一個網上的資料也很少,出問題不好定位。(達夢的錯誤碼比較簡單,就是一個負數,不像oracle是ora-錯誤碼,在百度時輸入一個負數搜索信息,跟一長串錯誤碼搜索效率差很遠)
準備工作:
1 達夢的資料庫管理工具預設不顯示行號,也不能自動補全,需要手動設置。行號設置方法:在sql編輯頁面,左側空白豎欄(一般編輯器顯示行號的地方)右擊,選擇”顯示行號“。自動補全設置方法:在sql編輯頁面空白處右擊,選擇“選項”,彈出的界面展開“查詢分析器”,進入“編輯器”配置頁面,選中“啟用SQL輸入助手”
2 裝完達夢資料庫後,需要啟動oracle相容模式sp_set_para_value(2,‘COMPATIBLE_MODE’,2);
,另外,需要啟動dbms_job包,SP_INIT_JOB_SYS(1)。改完設置後記得重啟。
遷移碰上的問題及解決方法:
1 使用達夢的資料庫遷移工具,把oracle的用戶整體遷移到達夢後,是變成一個模式,而不是用戶,使用起來不方便。
解決方法:達夢資料庫有用戶和模式兩個概念,庫表和存儲過程等是建在模式下麵的,而用戶則是獨立的,與安全和許可權功能掛鉤,這跟mysql比較像。達夢的用戶進行資料庫操作時,預設使用同名的模式,想訪問其它模式的元數據,需要顯式加模式名。所以為了跟oracle保持一致,在遷移完後,需要手工給達夢添加oracle同名用戶。
2 遷移後發現有一些存儲過程,包等缺失。
解決方法:遷移工具做得不是太好,有一些oracle資料庫的元素是不會自動遷移的,需要手工處理。例如oracle的type(達夢叫“類”),一些包含達夢資料庫關鍵字的存儲過程等。(在遷移日誌裡面沒報錯的,但也是可能沒遷成功,需要仔細檢查)
3 oracle建SEQUENCE裡面的關鍵字MINVALUE達夢不支持
4 達夢的關鍵字比oracle多很多,例如CONTEXT,bool,class,decode這些,oracle不是關鍵字,但達夢是。
解決方法:給這些使用了關鍵字的欄位名或者變數名加上"",並且轉換成大寫就可以了。例如"CLASS"
5 建了包,提示創建成功,編譯有錯,但沒有具體說明錯誤地方。
解決方法:可以在後面增加語句:alter package q$err_mgr compile;
6 提示“第3156 行附近出現錯誤[-3719]: 非法的基類名[DBMS_SQL]”
解決方法:首先確認DBMS_SQL包是否啟用(在左側“工具包”菜單右鍵,選擇啟用)。如果啟用了後還報這個錯,則需要檢查是否使用了某些DBMS_SQL的類型或者函數,在oracle有,但是在達夢沒有的。
7 編譯包時提示“第3494 行附近出現錯誤[-2193]:無效的方法名[func_name]"
解決方法:這種提示原因有很多,可能是確定在包裡面沒有定義這個func_name,也可能是func_name不在包頭裡面聲明,但在初始化代碼裡面調用。(oracle允許只在包體裡面定義,達夢不允許)。也可能是調用func_name的函數跟func_name都不在包頭聲明,但是在包體定義時,func_name出現位置比調用處更晚,在達夢這種是不允許的。
8 regexp系統函數提示“參數不相容”
解決方法:達夢的regexp系統函數的參數名與oracle的不一樣,如果原來在oracle指定了參數名,搬到達夢編譯時容易出現這個錯。改為非顯示命名函數參數就好。
9 出現提示“第646 行附近出現錯誤[-3325]:包/對象[package_name]解析失敗”,但646行代碼是空白行
解決方法:達夢的報錯位置不是太準確,這種情況下一般是上下文語法解析出現問題導致的。我碰到比較多的情況是在for迴圈語句裡面使用了case when ... end子句。達夢8對於case when支持不太好,容易把case when的end關鍵字與begin配對了,導致語法錯亂。我的解決方法是使用decode改寫case when
10 報錯提示“無法解析的成員訪問表達式[XXX] ”
解決方法:這類錯誤主要是因為其它包之類的編譯失效導致,需要具體分析再解決。有時會出現迴圈引用的情況(a包引用b包的函數,b包引用a的函數),達夢支持不太好,編譯a時提示b的函數有問題,編譯b時提示a的函數有問題。我的解決方法是建立一個c包,把一些代碼從a和b抽出來,避免迴圈引用。大部分時候迴圈引用是可以編譯過的,也可能是由於其它錯誤引起包編譯不過,但是系統沒提示好。這種情況下只要解決了另外的錯誤,這個迴圈引用編譯失敗的問題也就解決了。
11 提示“非法的基類名[ROWID]”
解決方法:我的代碼裡面使用了rowid類型變數,我直接改成number了
12 達夢對於重載(覆蓋)支持不太好
解決方法:oracle裡面兩個同名函數,參數一樣,只是一個是IN類型參數 ,一個是IN OUT參數,是被認為是兩個不同類型的函數,可以正常重載。但達夢認為是同一個函數,編譯時會出錯。解決辦法是把其中一個改名。另外,oracle裡面varchar2(64),varchar2(1024)是兩種不同的類型,可以支持重載兩個函數,參數為這兩種類型,但在達夢不支持。oracle裡面同名的CONSTANT變數定義,後出現的會覆蓋先出現的。但在達夢裡面不支持。提示“錯誤號: -2120 無效的變數名”
遷移過程中也許還會碰上其它問題,處理原則是查官方幫助文檔(在幫助菜單下麵搜索,同時在安裝目錄下麵也有很多pdf文件介紹),查百度,問官方支持。(我另了達夢的技術支持群,群里的南網工作人員還是挺熱心的)
有時官方支持也搞不清楚,需要自己通過刪減代碼,慢慢定位問題,再自己猜測出錯原因並嘗試解決。
另外,之前有人寫過一份教程《oracle遷移達夢常見問題彙總》 https://www.cndba.cn/foucus/article/4142 ,裡面介紹了不少遷移的經驗,也是值得借鑒的。