SQL Server 到 MySQL 的遷移 - 如何在 SQL Server 中刪除 UCS-2 代理對?
我的任務是將 SQL Server 2005 數據庫遷移到 MySQL 5.6(這些都是本地執行的數據庫伺服器),非常感謝一些幫助。
——–編輯 - 已回答—–
現在這個問題已經解決了。我使用 Remus Rusanu 的建議來查找具有這些代理對字元的行,
CHARINDEX
並決定使用它SUBSTRING
來排除麻煩的字元,如下所示:UPDATE test SET a = SUBSTRING(a, 1, (CHARINDEX(0x83dc, CAST(a AS VARBINARY(8000)))+1)/2 - 1) -- string before the unwanted character + SUBSTRING(a, (CHARINDEX(0x83dc, CAST(a AS VARBINARY(8000)))+1)/2 +1, LEN(a) ) -- string after the unwanted character WHERE CHARINDEX(0x83dc, CAST(a AS VARBINARY(8000))) % 2 = 1 -- only odd numbered charindexes (to signify match at beginning of byte pair character)
—————————–
- SQL Server 源數據庫有
latin1
排序規則(所以有 ISO 8859-1 字元集對嗎?)但沒有任何char/varchar
欄位(任何字元串欄位都是nvarchar/nchar
),因此所有這些數據都應該使用 UCS-2 字元集。- MySQL 目標數據庫需要 UTF-8 字元集。
我決定在最新版本的 MySQL 工作台中使用數據庫遷移工具包。起初它執行良好並按預期遷移了所有內容。但是在 SQL Server 數據庫中遇到 UCS-2 代理對字元時,我完全被絆倒了。
遷移工具包可複製表程序沒有提供非常有用的錯誤消息:
wstring 的字元集轉換期間出錯:沒有錯誤。
它也沒有提供有關導致問題的數據的任何欄位/行資訊,並且會在 100 行的塊內失敗。因此,在最後一次成功插入後搜尋 100 行後,我發現問題似乎是由其中一個 nvarchar 欄位中的兩個 UCS-2 字元引起的。它們在 UCS-2 字元集中被列為代理項對。它們特別是字元 DBC0 和 DC83(我通過查看該欄位的二進制數據並將字節對(小端序)與成功遷移的數據進行比較得到了這一點)。
當從 SQL Server 數據庫中刪除此代理對時,該行已成功遷移到 MySQL。
這是問題所在:
我試圖在測試 SQL Server 表中搜尋這些字元(這個圖表表只是一個 nvarchar 欄位的各種測試字元串)以準備替換腳本並不斷得到奇怪的結果……我一定做錯了什麼。
正在尋找
SELECT * FROM chartest WHERE text LIKE NCHAR(0xdc83)
將返回任何代理對字元(無論它是否使用 DC83),但顯然,僅當它是該欄位中唯一的字元(或該對的一部分)時。這沒什麼大不了的,因為無論如何我都想刪除這些實例(我不喜歡刪除這樣的數據,但我認為我們負擔得起)。
正在尋找
SELECT * FROM chartest WHERE text LIKE '%' + NCHAR(0xdc83) + '%'
將返回每一行!無論欄位中是否存在 unicode 字元,更不用說 DC83 字元了。有沒有更好的方法來查找和替換這些字元?或者我應該嘗試其他什麼?
我還嘗試將目標數據庫、表和欄位字元集設置為 UCS-2,但似乎沒有什麼區別。
我還應該提到,此遷移使用實時數據(約 50GB 數據庫!),而其中一個提供數據的站點已離線,因此任何解決方案都需要快速執行…
我非常感謝任何建議!如果我遺漏了任何資訊,請告訴我。
您需要從 UTF-8 獲取數據並使用 iconv 之類的東西將其轉換為 UCS-2LE。例如,使用範例中的字元:
echo "010000: dcb3" | xxd -r -s -0x10000 | iconv -f "UTF-8" -t "UCS-2LE" | xxd 0000000: 3307
現在我不確定 UTF-8 \xdcb3 是什麼字元,但顯然它對 UCS-2LE 的正確翻譯是
\U0733
. 如果您\0xDCB3
在 SQL Server 中有,則表示它在導入之前未翻譯成 UCS-2LE。您不應該在 NVARCHAR 欄位中有代理,UCS-2 是“代理不可知論”。請參閱UCS-2 與 UTF-16(不完全是 Kramer 與 Kramer)。我不是 MySQL 工具集的專家,所以我不能說應該執行 iconv 的步驟是什麼。
更新
要找到帶有代理項的記錄,您必須轉向二進製表示,因為任何字元函式都會將代理項威脅為“特殊”:。幸運的是,字元串操作函式也可以在具有預期語義的二進製文件上工作。例如。字元索引:
insert into test(a) values (N'a'); insert into test(a) values (NCHAR(0xdc83)); insert into test(a) values (N'b'); go select * from test where charindex(0x83dc, cast(a as varbinary(8000))) > 0;