Миграция от MSSQL към MySQL - проблеми с кодирането на char със сурогатни двойки UCS-2, как мога да ги премахна от MSSQL база данни?

Имам задача да мигрирам база данни на Microsoft SQL Server 2005 към MySQL 5.6 (и двата сървъра на база данни работят локално) и наистина ще оценя малко помощ.

-MSSQL изходната база данни има latin1 сортиране (така че има ISO 8859-1 символен набор нали?), но няма полета char/varchar (всяко поле за низ е nvarchar/nchar), така че всички тези данни трябва да използват знака UCS-2 комплект.

- Целевата база данни на MySQL иска набора от знаци UTF-8

Реших да използвам инструментариума за мигриране на база данни в най-новата версия на MySQL workbench. в началото работи добре и мигрира всичко според очакванията. Но бях напълно объркан, когато се натъкнах на UCS-2 сурогатни двойки знаци в базата данни MSSQL.

Програмата за копиране на инструментариума за миграция не предостави много полезно съобщение за грешка: „Грешка по време на преобразуване на набор от символи на wstring: Няма грешка“. Той също така не предостави никаква информация за поле/ред за причиняващите проблем данни и би се провалил в рамките на части от 100 реда. Така че след търсене в 100-те реда след последното успешно вмъкване открих, че проблемът изглежда е причинен от два знака UCS-2 в едно от полетата nvarchar. Те са изброени като заместващи двойки в набора от символи UCS-2. Те бяха по-конкретно символите DBC0 и DC83 (разбрах това, като разгледах двоичните данни за полето и сравних двойки байтове (little endian) с данни, които бяха мигрирани успешно).

Когато тази сурогатна двойка беше премахната от 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, но изглежда, че това няма значение.

Трябва също така да спомена, че тази миграция използва живи данни (~50 GB база данни!), докато един от сайтовете, които я захранват, е офлайн, така че всички решения за това трябва да имат бързо време за изпълнение...

Ще се радвам много на всякакви предложения! Моля, уведомете ме, ако има някаква информация, която съм пропуснал.


person JonM    schedule 22.03.2013    source източник


Отговори (4)


Имах тази грешка и сега открих източника на проблема. Трудно ми беше да разбера, така че може би това ще бъде полезно за някого, въпреки че осъзнавам, че моят проблем и заобиколното решение може да не са съвпадащи с първоначалния проблем на операционната система.

Мигрирам данни от MSSQL към MySQL и съдържанието, което се мигрира, е html съдържание от Sitecore CMS (целевата CMS е Drupal, между другото).

Открих, че получавам тази грешка, когато преобразувам базата данни и натискам записи, които съдържат Instagram-embeds. Instagram-вгражданията работят по начин, че вградените данни за публикация се копират в кода за вграждане (вместо да се зареждат асинхронно и т.н. - дори изображението е включено като base64-css...), и младите хора в днешно време са склонни да поставят много емотикони в своите описания на изображения (използвайки своите iPhone с Emoji клавиатура). Емотикони са представени от 4-байтови кодирани знаци, но MySQL utf8 позволява само 3-байтови кодирани уникод знаци.

Първоначалната ми грешка при стартиране на wbcopytables.exe (което е не-GUI начин за извършване на съветника за мигриране в MySQL Workbench) беше

Грешка по време на преобразуване на набор от знаци на wstring: Няма грешка

но надграждането на MySQL Workbench до най-нова версия (от 5.something на 6.x) прави грешката малко по-описателна, подсказвайки таблица и колона (уви, не ред):

ГРЕШКА: Не можа успешно да се преобразува UCS-2 низ в UTF-8 в таблица [MyDatabase].[dbo].[MyTable] (колона MyColumn). Оригинален низ: ...

Както и да е - решение *може* да бъде използването на utf8mb4, което би позволило емотикони. Прочетете повече тук.

Но изглежда, че е лоша идея да правите това напр. моят случай с Drupal.

И така - решението, което намерих, беше просто да премахна тези знаци в моя скрипт за мигриране. Няма смисъл да ги пазите за потребителите на въпросния сайт, тъй като те така или иначе се показват като правоъгълници на уеб страницата. Тъй като не можете да търсите и заменяте с регулярен израз в SQL Server, обработих данните с помощта на DAL и c# .NET и намерих помощта тук (много благодаря, Jon Skeet) - оказва се, че има шаблон за регулярен израз за съпоставяне на едната половина от сурогатна двойка в UTF-16. Вижте по-долу (и използвайте модела на друг език, ако е необходимо).

var noUcs2SurrogatePairsString = Regex.Replace(stringWithUcs2SurrogatePairs, @"\p{Cs}", string.Empty);
person Frederik Struck-Schøning    schedule 20.01.2015

Днес имах много подобен проблем и открих, че е причинен от празни низове, замених ги с NULL или стойност, която не представлява данни, и миграцията работи добре.

person Paddy Green    schedule 18.05.2016

Реших просто редактиране на „скрипт за импортиране на данни.cmd“, където той чете колони „Като NVARCHAR“, като замених тези само с „VARCHAR“.

Забележка: Колоните на моята таблица вече бяха тип VARCHAR, така че... по някаква глупава причина скриптът за миграция неправилно ги прехвърли към тип UNICODE (NVARCHAR).

person Roger Barreto    schedule 05.04.2016
comment
Това ми помогна. Преминавах от VARCHAR към VARCHAR, но изходният скрипт CAST към NVARCHAR/NCHAR. Поправих скрипта, както беше споменато, и това реши проблема ми. - person Richard Adleta; 06.07.2016

Този проблем вече е решен. Използвах предложението на потребител 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)
person JonM    schedule 26.03.2013
comment
Това се случва с мен, имам таблица, наречена tblSenderReciever - получавам същата грешка на tblSenderReciever. В тази таблица, когато стартирам тази заявка на САМО nvarchar, 0 реда са засегнати.. някаква идея какво се случва? - person maor10; 06.07.2014
comment
@user1005978 Насочвах се към конкретни символи, които ми създаваха проблем. Намерих тези знаци само чрез търсене в конкретната партида от 100 реда, на която софтуерът за мигриране се провали. Можете ли да идентифицирате кои редове/полета имат този проблем? След това можете да идентифицирате всички потенциално обезпокоителни символи (в моя случай това беше конкретно UCS-2 сурогатната двойка знаци DBC0 и DC83). - person JonM; 09.07.2014