最近接手一起老項目數據庫 SQL Server 到 MySQL 的遷移。因此遷移前進行了一些調查和總結。下面是一些 SQL Server 到 MySQL 的遷移方法。
1. 使用 SQLyog 遷移
具體方法可以參加:http://www.cnblogs.com/gaizai/p/3237907.html
優點:該遷移方法很簡單,靈活,遷移時,可以進行字段的修改,比如在sql server中原來是datetime,然後遷移到mysql時你可以配置成timestamp;
成功率很高;
缺點:遷移很慢!這是該方法最大的缺點,如果表的數據量達到幾十萬行,甚至幾百萬行,你會發現遷移起來真的很慢。明顯比其他遷移方法慢很多。
2. 使用 powerdesigner 和 sql server 的腳本導出功能 來遷移
第一步:該方法首先使用 powerdesigner,對sql server數據庫,進行逆向工程,得到E-R圖,然後生成MySQL的建表語句。完成數據庫結構的遷移;
當然表結構的遷移,不使用powerdesigner一樣也是可以的。比如我將表結構導出成語句,然後手動進行修改,然後在MySQL中運行,也是一樣的;
第二部:然後使用 sql server的工具 SSMS,將sql server數據庫中的表的數據,導出成insert語句,每個表對應導出一個文件,然後對文件進行一些處理,
然後導入到MySQL數據庫中。
具體的對 sql server 導出的sql文件的處理方法,參見:http://www.cnblogs.com/digdeep/p/4822499.html
3. 使用Oracle MySQL Server 官方的 workbeach 工具進行遷移
mysql官方有兩篇 sql server 遷移到 mysql的指導手冊,可以參考:
http://www.mysql.com/why-mysql/white-papers/guide-to-workbench-migration-wizard/
http://www.mysql.com/why-mysql/white-papers/guide-to-migrating-from-sql-server-to-mysql/
上面的連接中可以下載到pdf文件,安裝文件的說明,使用 workbeach 工具就能進行遷移。因為 workbeach 有30天的使用期,所以完全不需要擔心;
在workbench 連接sql server時,用戶需要有 view any database 的權限。不然workbench無法訪問sql server的表結構的元數據,從而無法進行遷移。
還有使用 Navicat 來進行遷移的方法,方法和 SQLyog 是類似的。
4. 三種方法比較
方法一只適合數據量小的遷移方法,如果數據量大,遷移時間短,基本是不適合的;
方法二是比較好的方法,缺點就是sql server導出的insert腳本中 datetime字段和decimal需要自己寫代碼進行轉換,稍微有點麻煩;
第三種方法應該是最佳的選擇,比較簡單,速度也快,又不需要自己進行字段的處理。
所以對於數據量比較大的情況,應該選擇方法三或者方法二。
5. 遷移需要注意的一些問題
sql server 在向 mysql 遷移時,需要注意的一些問題,在連接 http://www.mysql.com/why-mysql/white-papers/guide-to-migrating-from-sql-server-to-mysql/ 的文檔中都有說明。下面是一些具體的注意事項:
1)唯一索引的不同,sql server的唯一索引的字段只能允許存在一個null值,而mysql,一直oracle中唯一索引對應的字段都允許存在多個null值;
2)ifnull 與 isnull ,sql server使用的是 ifnull,而mysql 中要使用 isnull:
<update id="updateModelAccuracyById" parameterClass="java.util.Map"> update model_model set accuracy_num=ifnull(accuracy_num,0) + 1, accuracy_total=ifnull(accuracy_total,0) + #accuracyTotal:DECIMAL# where id=#id:BININT# and status=1 </update>
3)所有的分頁sql都需要重寫:
SQL server的分頁(使用的是 row_number() over(......)):
<select id="getModelChoiseListByUserId" parameterClass="java.util.Map" resultClass="net.xxx.xxx.dataobject.model.ModelChoiseVo"> select * from (select row_number() over(order by c.choise_time desc) as rowid, c.id as id,m.gid as gid,m.member_id as memberId,mb.g_Member_Nickname as memberName, mb.g_Member_Mobile as memberMobile,c.user_id as userId, ... ... m.order_num as orderNum,m.model_satisfaction as modelSatisfaction,m.height as height, m.professional_type professionalType from model_model m inner join model_choise c on m.id=c.model_id inner join Members mb on mb.g_MemberID=m.member_id where m.status=1 <dynamic > <isNotNull prepend="and" property="userId"> c.user_id = #userId:BIGINT# </isNotNull> <isNotNull prepend="and" property="status"> c.status = #status:INTEGER# </isNotNull> </dynamic> ) tt where rowid >= #minRow:INTEGER# and rowid <= #maxRow:INTEGER# </select>
用mysql重寫:
<select id="getModelChoiseListByUserId" parameterClass="java.util.Map" resultClass="net.xxx.xxx.dataobject.model.ModelChoiseVo"> select c.id as id,m.gid as gid,m.member_id as memberId,mb.g_Member_Nickname as memberName, mb.g_Member_Mobile as memberMobile,c.user_id as userId, m.id as modelId,c.status as status, c.pay_amount as payAmount,c.accuracy as accuracy, ... ... m.order_num as orderNum,m.model_satisfaction as modelSatisfaction,m.height as height, m.professional_type professionalType from model_model m inner join model_choise c on m.id=c.model_id inner join Members mb on mb.g_MemberID=m.member_id where m.status=1 <dynamic> <isNotNull prepend="and" property="userId"> c.user_id = #userId:BIGINT# </isNotNull> <isNotNull prepend="and" property="status"> c.status = #status:INTEGER# </isNotNull> </dynamic> order by c.choise_time desc limit #minRow:INTEGER#, #maxRow:INTEGER# </select>
4)存儲過程的遷移是最麻煩的:
存儲過程的語法存在很大的不同。
http://www.mysql.com/why-mysql/white-papers/guide-to-migrating-from-sql-server-to-mysql/ 的文檔中有一些說明。
下面是一些mysql存儲過程的參考文章:
http://www.cnblogs.com/digdeep/p/4818660.html
http://www.cnblogs.com/digdeep/p/4814020.html