5

我的任务是将 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 数据库!),而其中一个提供它的站点已脱机,因此任何解决方案都需要快速运行...

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

4

4 回答 4

4

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

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

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

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

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

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

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

无论如何-*可以*使用utf8mb4一个允许表情符号的解决方案。在这里阅读更多。

但看起来,在我的 Drupal 案例中这样做是个坏主意。

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

var noUcs2SurrogatePairsString = Regex.Replace(stringWithUcs2SurrogatePairs, @"\p{Cs}", string.Empty);
于 2015-01-20T13:48:09.387 回答
2

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

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

于 2016-04-05T22:31:19.910 回答
2

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

于 2016-05-18T07:55:20.463 回答
0

现在这个问题已经解决了。我在这里使用用户 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)
于 2013-03-26T08:55:10.297 回答