MSSQL 到 MySQL 迁移 - UCS-2 代理对的字符编码问题,如何从 MSSQL 数据库中删除这些?

Posted

技术标签:

【中文标题】MSSQL 到 MySQL 迁移 - UCS-2 代理对的字符编码问题,如何从 MSSQL 数据库中删除这些?【英文标题】:MSSQL to MySQL migration - char encoding issues with UCS-2 surrogate pairs, how can I remove these from MSSQL database? 【发布时间】:2013-03-12 09:55:59 【问题描述】:

我的任务是将 Microsoft SQL Server 2005 数据库迁移到 mysql 5.6(它们都是本地运行的数据库服务器),非常感谢一些帮助。

-MSSQL 源数据库有 latin1 排序规则(所以有 ISO 8859-1 字符集对吗?)但没有任何 char/varchar 字段(任何字符串字段都是 nvarchar/nchar)所以所有这些数据都应该使用 UCS -2 字符集。

-MySQL 目标数据库想要字符集 UTF-8

我决定在最新版本的 MySQL 工作台中使用数据库迁移工具包。起初它运行良好,并按预期迁移了所有内容。但是在 MSSQL 数据库中遇到 UCS-2 代理对字符时,我完全被绊倒了。

迁移工具包可复制表程序没有提供非常有用的错误消息:“wstring 的字符集转换期间出错:没有错误”。它也没有提供有关导致问题的数据的任何字段/行信息,并且会在 100 行的块内失败。因此,在最后一次成功插入后搜索 100 行后,我发现问题似乎是由其中一个 nvarchar 字段中的两个 UCS-2 字符引起的。它们在 UCS-2 字符集中作为代理项对列出。它们特别是字符 DBC0 和 DC83(我通过查看该字段的二进制数据并将字节对(小端序)与成功迁移的数据进行比较得到了这一点)。

当从 MSSQL 数据库中删除此代理对时,该行已成功迁移到 MySQL。

问题来了:

我试图在一个测试 MSSQL 表中搜索这些字符(这个图表表只是一个 nvarchar 字段的各种测试字符串)来准备一个替换脚本并不断得到奇怪的结果......我一定做错了什么。

搜索

SELECT * FROM chartest WHERE text LIKE NCHAR(0xdc83)

将返回任何代理对字符(无论它是否使用 DC83),但显然,仅当它是该字段中唯一的字符(或该对的一部分)时。这没什么大不了的,因为无论如何我都想删除这些实例(我不喜欢删除这样的数据,但我认为我们负担得起)。

搜索

SELECT * FROM chartest WHERE text LIKE '%' + (NCHAR(0xdc83))+ '%'

将返回每一行!不管字段中是否存在 unicode 字符,更不用说 DC83 字符了。有没有更好的方法来查找和替换这些字符?或者我应该尝试其他什么?

我也尝试过将目标数据库、表和字段字符集设置为 UCS-2,但似乎没有任何区别。

我还应该提到,此迁移使用实时数据(约 50GB 数据库!),而其中一个提供数据的站点已脱机,因此任何解决方案都需要快速运行...

非常感谢任何建议!如果我遗漏了任何信息,请告诉我。

【问题讨论】:

【参考方案1】:

此问题现已解决。我使用用户Remus Rusanu's 建议here 使用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)

【讨论】:

这发生在我身上,我有一个名为 tblSenderReciever 的表 - 我在 tblSenderReciever 上遇到了同样的错误。在此表中,当我在 ONLY nvarchar 上运行该查询时,有 0 行受到影响。知道发生了什么吗? @user1005978 我的目标是导致我出现问题的特定字符。我只是通过搜索迁移软件失败的特定批次的 100 行才找到这些字符。您是否能够确定哪些行/字段存在此问题?之后,您可以识别任何潜在的麻烦字符(在我的例子中,它特别是 UCS-2 代理对字符 DBC0 和 DC83)。【参考方案2】:

我遇到了这个错误,现在我找到了问题的根源。我很难找到答案,所以也许这对某人有用,即使我意识到,我的问题和解决方法可能不是匹配 op 的原始问题。

我正在将数据从 MSSQL 迁移到 MySQL,正在迁移的内容是来自 Sitecore CMS 的 html 内容(目标 CMS 是 Drupal,顺便说一句)。

我发现,在转换包含 Instagram-embeds 的数据库和点击记录时出现此错误。 Instagram-embeds 的工作方式是将嵌入的帖子数据复制到嵌入代码中(而不是异步加载,等等 - 甚至图像也包含为 base64-css ......),而年轻人现在倾向于在他们的图像描述中加入很多表情符号(使用带有表情符号键盘的 iPhone)。 Emoji 由 4 字节编码字符表示,但 MySQL utf8 仅允许 3 字节编码 unicode 字符。

我在运行wbcopytables.exe(这是在 MySQL Workbench 中执行迁移向导的非 GUI 方式)的初始错误是

wstring的字符集转换时出错:没有错误

但是将 MySQL Workbench 升级到最新版本(从 5.something6.x)会使错误更具描述性,提示表和列(唉,不是行):

错误:无法成功将表中的 UCS-2 字符串转换为 UTF-8 [MyDatabase].[dbo].[MyTable](MyColumn 列)。 原始字符串:...

无论如何 - 一个解决方案*可能*是使用utf8mb4,这将允许表情符号。阅读更多here。

但看起来,在例如 a bad idea 中执行此操作我与 Drupal 的情况。

所以 - 我最终得到的解决方案只是在我的迁移脚本中去除这些字符。为相关站点的用户保留这些是没有意义的,因为它们无论如何都在网页上显示为矩形。由于您无法在 SQL Server 中使用正则表达式进行搜索和替换,因此我使用 DAL 和 c# .NET 处理了数据,并找到了帮助 here(非常感谢,Jon Skeet) - 结果是用于匹配 UTF-16 中代理对的一半的正则表达式模式。见下文(如果需要,可以使用另一种语言的模式)。

var noUcs2SurrogatePairsString = Regex.Replace(stringWithUcs2SurrogatePairs, @"\pCs", string.Empty);

【讨论】:

【参考方案3】:

我解决了仅编辑“导入数据脚本.cmd”的问题,它通过仅将列替换为“VARCHAR”来读取“As NVARCHAR”列。

注意:我的表列已经是 VARCHAR 类型,所以...由于某些愚蠢的原因,迁移脚本不正确地将其转换为 UNICODE (NVARCHAR) 类型。

【讨论】:

这帮助了我。我正在从 VARCHAR 移动到 VARCHAR,但输出的脚本 CAST 到 NVARCHAR/NCHAR。我如前所述修复了脚本,这解决了我的问题。【参考方案4】:

我今天遇到了一个非常相似的问题,发现是空字符串引起的,将它们替换为 NULL 或表示没有数据的值,并且迁移工作正常。

【讨论】:

以上是关于MSSQL 到 MySQL 迁移 - UCS-2 代理对的字符编码问题,如何从 MSSQL 数据库中删除这些?的主要内容,如果未能解决你的问题,请参考以下文章

仅将表数据从 MSSQL 迁移到 MySQL

Mssql Server 到 MySql 之间的迁移视图

从 MSSQL 迁移到 MYSQL 错误 1064 MYSQL Workbench

MSSQL 到 MySQL 数据库迁移

将大表从 MySql 迁移到 MsSql

从 MSSQL 迁移到 postgresql 或 mysql [关闭]