Как мне исправить кодовую страницу в преобразовании поиска SSIS на 65001?

#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