把 Microsoft SQL Server 的 table schema 和資料轉到 MySQL

碰到幾個需求,要把不同資料庫系統的資料表結構或資料轉成 MySQL,留個操作紀錄。

一、Microsoft SQL Server 的資料表和結構轉到 MySQL

情況是網站使用的關聯式資料庫,主要是用 Microsoft SQL Server(MSSQL),虛擬主機商提供資料庫自動備份,但只能備份 MySQL,為了完成「備份資料庫」這個需求,想要先試試把 MSSQL 裡面的一堆資料表和資料表結構先搬過去。
資料的話另外寫程式去撈然後 insert 進去。

環境資訊

來源資料庫(MSSQL),內有數十個資料表,裡面有一堆欄位,沒有 SP 或 Trigger,經由 SELECT @@VERSION AS ‘SQL Server Version’ 得到

Microsoft SQL Server 2012 (SP4-GDR) (KB4583465) – 11.0.7507.2 (X64) Nov 1 2020 00:48:37 Copyright (c) Microsoft Corporation Web Edition (64-bit) on Windows NT 6.1 X64 (Build 7601: Service Pack 1)

用 select serverproperty(‘Edition’) 得到

Web Edition (64-bit)

目的資料庫(MySQL),僅有開好資料庫,裡面完全是空的,經由 SELECT VERSION(); 得到

‘5.5.51-38.1-log’

版本有點低,幸好資料裡不會需要存 emoji

MySQL WorkBench 的 Database Migration Wizard – 失敗

官方說明 MySQL :: MySQL Workbench Manual :: 10.5 Microsoft SQL Server Migration

看到滿多篇教學都用這個,但不知道為何沒成功。

操作結果: 來源資料庫跟目標資料庫在 test connection 時都是 Connection sussceeded,但是在 schemas selection 時不知為何一片空白

軟體的 tool 選單裡面還有另一個 schema 工具,但看起來無法處理兩個不同的資料庫系統,不符合本次需求。

SQL Server Management Studio (SSMS) 的匯入和匯出精靈 – 失敗

官方說明 連線至 MySQL 資料來源 (SQL Server 匯入和匯出精靈)

要安裝 .NET Framework Data Provider for MySQL,操作時才會有 MySQL 的選項可以選,不然下拉選單裡預設都是一些微軟自己的相關商品。

操作結果:

無法擷取來源和目的地資料的資料行資訊,或來源資料行的資料類型未正確對應至目的地提供者可用的資料類型。

不同的關聯式資料庫產品本來就會有不一樣的功能,不用 ORM 的話,連寫程式時的 raw-sql 指令也略有差異,甚至同一個產品的不同版本也會有各種欄位類型和相關屬性的差異,諸如升降版、資料轉移等操作無疑是一大地雷,除非是依小時收費或是閒著沒事幹,沒事不要輕易嘗試。

這次許多資料表內的許多欄位有 MySQL 不認得的欄位類型,花時間人工一一在匯入和匯出精靈的操作介面中修正後,終於可以按下一步了,結果…

錯誤 0xc002f210: 準備 SQL 工作 1: 執行查詢 … 失敗,發生下列錯誤:… 可能的失敗原因: 查詢發生問題、未正確設定 “ResultSet” 屬性、未正確設定參數,或未正確建立連接。

結果又是一場空。

Navicat Premium 的資料傳輸工具 – 成功

官方說明 Navicat – 資料傳輸

把帳密打進去,也不需要特地手動調整欄位類型,然後就把資料表+schema+資料內容通通轉移過去了。

檢查了一下轉換後的 MySQL 資料表
欄位 collation 是開 uft8_general_ci, chart set 是 utf8 ,至少中文字都正常,沒變成問號
本來 nvarchar(max) 的欄位自動轉成 longtext
primary key 跟 nullable 還在
沒勾遇到錯誤時停止,轉換時也沒顯示錯誤,但第一次轉完之後發現少了幾個資料表?
一模一樣設定再操作一次,就又正常了

雖然不盡完美,但還是省了不少時間,真是神工具,趕快野人獻曝,分享給有類似需求的衰鬼工作人員。

不過 Navicat 軟體跟上述兩者不同,是要花錢買的,僅有14天試用,商業使用年度訂閱USD 699.99,永久授權USD 1,399.00。
很佛心的是 14 天免費試用期提供的是全功能版本,而且完全不用填任何 email 或個資就可以下載&使用,這才是真心做好產品的,不是搞一些莫名其妙的 Growth Hacker 手法,像是下載前要先填公司名稱、email、姓名,安裝時要先註冊會員、綁信用卡,下載後沒使用還會寄信通知,分享給朋友還可以解鎖功能或賺點數,移除前還會跳網頁出來請人填問券,工程師好好做產品的時間都被一些業務人行銷人拿來做整人的東西。

結論

1.只是論資料表備份的話,省錢花時間的土炮備份法也不少,但有些東西不是花自己錢的,有問題也賠不起的,就還是不要這樣亂搞了,趕快趁 Navicat 的試用期內完成資料表和資料表結構的轉移,後面每日備份需求還是得自行處理了。
2.一個簡單的 mssql to mysql 關鍵字,又可見 Google 搜尋引擎 AI 的不精準度,有些排名名列前茅的內容,點進去內文講的是 mysql to mssql,有些只是有介紹到兩種資料庫,根本不談轉移,一堆不相干的東西,文中講的軟體一個一個試,真的很花時間。
3.可惜這應該是個冷門題目,不然如果是有心人士的話,應該弄個什麼資料庫轉移工具/檢查工具,再弄個美滋滋的官網,使用者下載執行,輸入資料庫帳密和連線資訊之後,來給異地備份五鬼搬運法,偷搬完之後隨便吐個錯誤訊息,真是厲害了,真的有心要搞網路詐騙就是這麼簡單,在網路上還敢隨便亂下載軟體啊?
4.備份只是第一集,遇到問題如何還原回去才又是苦難的開始…

二、PostgreSQL 的資料表&結構&資料整個轉到 MySQL

情況是活動網站在以小時計費的機器上使用 PostgreSQL 資料庫,活動結束後可能還有一些資料查詢跟產生名單的需求,所以把資料庫搬到每年固定花費的便宜機器上來,因為便宜機器上只有 MySQL,所以同時要搬家+轉換系統的需求。

來源資料庫(PostgreSQL),經由 SELECT version(); 和 SHOW server_version; 得到

PostgreSQL 14.4 on x86_64-pc-linux-gnu, compiled by gcc 和 14.4

目的資料庫(MySQL),僅有開好資料庫,裡面完全是空的,經由 SELECT VERSION(); 得到

‘5.5.51-38.1-log’

dbeaver 的 Export Data – 失敗

之前撈資料時都使用 dbeaver,Export Data 裡面有個 Database 的選項,操作步驟大致可參考 DBeaver Documentation – Data migration試試看不同資料庫系統能不能硬上?

果然不行,建立 target table 的時候就出錯了。

MySQL WorkBench 的 Database Migration Wizard – 失敗

先參考 MuSQL Blog 一篇超久以前的文章 MySQL Blog Archive – Set up and configure PostgreSQL ODBC drivers for the MySQL Workbench Migration Wizard,安裝最下面那個最新版本的 psqlodbc driver,我是 Windows,所以沒有管 mac 跟 linux 那堆還要另外 sudo 的指令。
Database Migration Wizard 連線時報錯 FATAL : no pg_hba.conf entry for host…,連都沒連上,更別談資料庫轉移了。

Navicat Premium 的資料傳輸工具 – 成功一半?

最後又拿 NaviCat 出來用,一樣也是無腦選一選就自動把資料表都建好,資料通通搬完了。中文字也沒有變成問號,可喜可賀。

那對於資料欄位類型壓根不同的處理得怎樣呢?
1.原始的 PostgreSQL 資料庫有用到 jsonb 欄位類型,select 時可以用 (user.json_data -> 'name') AS "name"user.json_data->>'name' IS NOT NULL 用 key name 查 json 裡面的資料。
Navicat 轉換後在 MySQL 變成 longtext,這不怪軟體,畢竟 MySQL 5.7.8 之後才原生支援 json 欄位類型,反正裡面存的資料不太重要,不太需要單純取出來用。
2.原始資料庫有用到 uuid 欄位類型,轉換後變成 char
3.原始資料庫的 bool 欄位類型,轉換後變成 varchar,欄位資料變成 F 或 T,不過還好那個欄位的資料沒用到,壞了就算了。
4.原始資料庫的 timestamptz 欄位類型,字串長得像 2022-08-02 19:47:20.686 +0800,結果時間欄位的轉換不如預期,變成少了8小時的時間(如此例的資料會變成 11:47)。

幸好這個使用情境,跟最上面那個無人值守備份的不一樣,資料有問題就再人工處理一次就好了。把原始資料表的資料用 csv 匯出,寫程式把 csv 裡的日期讀出來,處理成正常的再 update 回去,就人工再修吧….

Tags: #sql
留言:

近期熱門 Hot Posts