#sql-server #ssis #collation
#sql-server #ssis #сопоставление
Вопрос:
У меня есть SQL server 2019, база данных и таблицы, для которых установлено значение Latin1_General_100_CI_AS_SC_UTF8 code
desc
, соответствующая таблица и столбцы имеют оба параметра.
В проекте SSIS единый компонент потока данных:
У меня есть CSV-файл UTF-8, прочитанный с подключением к плоскому файлу, текстовый столбец code
для сопоставления равен DT_STR, 65001
У меня есть поиск, для которого установлено значение «Полный кэш» и загружается таблица Latin1_General_100_CI_AS_SC_UTF8, но SSIS считает, что столбцы varchar DT_STR, 1252
Наконец code
, как в CSV, так и в lookup сопоставляются и desc
отправляются в таблицу назначения, которая находится в той же сортировке Latin1_General_100_CI_AS_SC_UTF8. Для целевого компонента установлено значение AlwaysUseDefaultCodePage True
и DefaultCodePage 65001
.
Теперь я получаю сообщение об ошибке, в котором говорится, что столбец содержит более одной кодовой страницы и не может запустить пакет.
Если бы не неправильно помеченный 1252, этот пакет должен был бы запуститься. Я полагаю, что это как-то связано с ExternalMetadataXml
, который доступен только для чтения и говорит, что все мои столбцы lookup varchar являются CodePage="1252"
.
Если я вручную отредактирую package .dtsx с помощью npp и заменю все экземпляры 1252 на 65001, пакет может запуститься и, похоже, будет делать то, что я ожидал, если я больше никогда не буду прикасаться к компоненту поиска.. Это кажется немного запутанным решением, но я надеюсь, что есть кто-то еще, у кого есть более чистый способ исправить это. Спасибо.
Комментарии:
1. Вы изменили кодовую страницу в своем исходном объекте?
Ответ №1:
С оговоркой о том, что я «тупой американец», который не имеет дела с неанглоязычными данными, но недавно работал с другом над использованием массового импорта с данными UTF-8, вот что я вижу.
У меня есть файл значений, разделенный каналами, который выглядит следующим образом
level|name
7|"Ovasino Poste de Santé"
Notepad указывает, что я сохранил его как UTF-8.
Я создал два плоских менеджера файловых подключений в SSIS: Codepage65001STR и Codepage65001WSTR. Они оба используют кодовую страницу 65001 (UTF-8)
На вкладке дополнительно для варианта STR я оставил тип данных как DT_STR
На вкладке дополнительно для варианта WSTR я изменил тип данных на DT_WSTR
Я также создал таблицу и загрузил в нее те же данные
DROP TABLE IF EXISTS dbo.dba_286478;
CREATE TABLE dbo.dba_286478
(
level int NOT NULL
, name varchar(75) COLLATE Latin1_General_100_CI_AS_SC_UTF8
)
INSERT INTO dbo.dba_286478
(
level
, name
)
VALUES
(
7 -- level - int
, 'Ovasino Poste de Santé' -- name - varchar(75)
);
DROP TABLE IF EXISTS dbo.dba_286478;
CREATE TABLE dbo.dba_286478
(
level int NOT NULL
, name varchar(75) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);
Затем я создал задачу потока данных с источником плоского файла, используя разные менеджеры соединений с плоскими файлами, и добавил средства просмотра данных между ними и пустой производный столбец (поэтому у меня была точка привязки для средства просмотра данных).).
Я сделал то же самое с источником OLE DB, указывающим на мою таблицу, а также с пользовательским запросом
SELECT
T.level
, CAST(T.name AS varchar(75)) AS name
FROM
dbo.dba_286478 AS T;
а также явно определять сопоставление, поскольку оно ничем не отличается в SSIS
, CAST(T.name COLLATE Latin1_General_100_CI_AS_SC_UTF8 AS varchar(75)) AS name
Все результаты показывают одно и то же, последнее слово — Санте с ударением. Если бы UTF-8 не произошел, он отображался бы как Santé
На данный момент не имеет значения, используем ли мы DT_STR или DT_WSTR в нашем определении столбца источника плоского файла, компонент понимает UTF-8 и UTF-16.
Свойства, метаданные каждого. Кодовая страница 65001 STR выглядит так, как ожидалось. кодовая страница 65001 и тип данных DT_STR
Unicode, DT_WSTR выглядит хорошо
Однако компоненты OLE — это другое животное. Компонент возвращает метаданные DT_WSTR (полный Юникод / UTF-16) независимо от того, выполняем ли мы явное приведение к DT_STR, необязательно указывая параметры сортировки, или пропускаем естественные метаданные.
В любом случае, он не обнаруживает кодовую страницу / параметры сортировки и просто говорит, что нет, вы в Юникоде
Итак, когда мы пытаемся использовать задачу поиска с помощью диспетчера соединений OLE DB, мы можем ожидать и получать ту же невозможность разграничения между строкой UTF-8/ varchar и UTF-16 / nvarchar
Ошибка будет указывать, и это правда, DT_STR не может соответствовать DT_WSTR
Не удается сопоставить входной столбец ‘name’ со столбцом поиска ‘name’, поскольку типы данных не совпадают.
Итак, что мне делать?
У вас должно быть выравнивание по типу, чтобы компонент поиска работал, что означает, что исходные данные должны иметь тип DT_WSTR
. Вы можете либо ввести данные из плоского файла в формате Unicode, либо оставить их в виде строки с кодовой страницей 65001. Если вы идете по последнему маршруту, то вам нужно выполнить копию, производный столбец или преобразование данных для этого столбца и использовать его в компоненте поиска.
Если вы извлекаете текст из компонента поиска, он теперь находится в вашем конвейере в формате Unicode, поэтому вы, вероятно, захотите преобразовать его в строковый тип с кодовой страницей. Опять же, будет использоваться производный столбец или преобразование данных.
OLE-компоненты SSIS не понимают UTF8
Мы видели с помощью компонента source и lookup, что SSIS будет обрабатывать строки UTF-8 как UTF-16, но я предположил, что он отлично справится с сохранением в таблице. Не так много.
Моя сортировка сервера Latin1_General_100_CI_AI_SC_UTF8
, и хотя я переключил чувствительность к акценту между определением сервера и таблицы dbo.dba_286478
, в данном случае это не имеет значения, поскольку это UTF-8 полностью.
Для моего источника плоского файла я использую файл на основе STR, который содержит метаданные, показанные выше, с желтой подсветкой. Кодовая страница 65001 для типа данных DT_STR — это то, что нам нужно.
Я добавил назначение OLE DB и указал на него в своей таблице, в которой снова столбец «name» определен как UTF-8
name varchar(75) COLLATE Latin1_General_100_CI_AS_SC_UTF8
Проверьте эту ошибку!
Ошибка проверки. Задача потока данных Назначение OLE DB [138]: столбец «имя» не может быть обработан, поскольку для него указано более одной кодовой страницы (65001 и 1252).
В этом потоке данных задействована только кодовая страница 65001, и, тем не менее, что-то в пространстве SSIS выводит / по умолчанию кодовую страницу 1252 во время проверки.
Заставить его работать
Компоненты в задаче потока данных были созданы с учетом подключений к OLE DB. Вот почему задача поиска поддерживала подключения OLE DB для 2005, 2008 и, возможно, 2008R2? Давным-давно я знаю, но опция диспетчера подключений к кэшу (она же что-то еще) была добавлена в более поздних итерациях из-за необходимости использовать что-то помимо OLE-менеджеров соединений, особенно учитывая, что тогда толчок заключался в том, чтобы отказаться от драйвера OLE.
An ADO.NET Диспетчер подключений в этом случае работает немного лучше, чем OLE, и это, вероятно, то, что вам придется использовать для работы с данными UTF8 в пакете SSIS. При представлении в таблицу он будет неявно преобразован в UTF-16, а затем SQL Server вернет его обратно в пространство UTF-8 (насколько я могу судить).
Для справки, ввод данных UTF-8 в конвейер с источником ADO по-прежнему будет помечен как DT_WSTR / UTF-16 / unicode.
Но вы можете поместить кодовую страницу DT_STR 65001 в ADO.NET Назначение без ошибки несоответствия кодовой страницы, как я вижу для назначения OLE DB.
Данные из базы данных будут отображаться как DT_WSTR независимо от того, как вы вводите их в конвейер. Это означает, что вы можете определить и OLE, и диспетчер соединений ADO для использования компонента поиска как есть.
Или вы можете добавить шаг предшествующего потока данных для заполнения диспетчера подключений кэша и иметь только ADO.NET диспетчер подключений. Вы должны были пойти по этому пути, преобразовать данные DT_WSTR в DT_STR с кодовой страницей 65001 и сохранить эти данные в кэше.
DFT - Populate Cache -> DFT - Load data
DFT — заполнение кэша
ADO.NET Source -> Data Conversion -> Cache Connection Manager
DFT — загрузка данных
Flat File Source -> Lookup Component -> ADO.NET Destination
Перекрестный ответ от https://dba.stackexchange.com/questions/286478/how-do-i-fix-the-code-page-in-ssis-lookup-transformation-to-be-65001/286520#286520
Комментарии:
1. спасибо за супер подробный ответ, однако это не очень помогает в моей ситуации, поскольку мой столбец на стороне сервера — VARCHAR UTF8, поэтому, если бы я работал в DT_WSTR, я бы закончил с другим преобразованием, прежде чем я смогу сохранить его в БД. У меня было 2-е возможное решение, которое заключалось в использовании другого плоского файла для поиска вместо поиска OLE, который похож на то, что вы рекомендовали
2. Проделал еще немного работы. Насколько я могу судить, вы застряли с преобразованиями с данными UTF-8, но ADO.NET подключение, по крайней мере, позволит вам сохранить данные в базе данных, чего не будет в пункте назначения OLE DB.
3. И «помощь», которую пытается предоставить мой ответ, заключается в том, что «инструментарий на самом деле не поддерживает то, что вы пытаетесь сделать», я найду подходящий пользовательский голосовой канал, я могу поднять это как проблему.
4. fwiw, виджет назначения OLE позволяет указать
AlwaysUseDefaultCodePage
иDefaultCodePage
в свойствах. Если вы установите True и 65001, вы сможете сохранить в БД. Я уже это сделал, проблема в том, что виджет поиска не имеет этих реквизитов
Ответ №2:
Похоже, вы не изменили кодовую страницу в своем диспетчере подключений к плоским файлам. Откройте диспетчер подключений, и там есть выпадающее меню для кодовой страницы, выберите 65001 для UTF-8 там.
Затем вам, вероятно, потребуется изменить задачу потока данных, поскольку узлы (до любых преобразований производных столбцов, которые вы должны преобразовать в кодовую страницу), скорее всего, будут обрабатывать данные как 1252, и вы получите сообщение об ошибке, поскольку SSIS не допускает неявных преобразований.
Комментарии:
1. привет, спасибо за ваш ответ, плоский файл установлен правильно, столбец 65001 из плоского файла. проблема заключается в чтении подстановки из sql с использованием OLE, SSIS почему-то считает, что varchar равен 1252, когда он должен быть 65001, потому что сопоставление sql server равно UTF8, а кодовая страница таблицы равна 65001