SQL Server - конвертировать varchar в другую сортировку (кодовая страница) для исправления кодировки символов

Я запрашиваю базу данных SQL Server, которая использует сортировку SQL_Latin1_General_CP850_BIN2. Одна из строк таблицы имеет varchar со значением, которое содержит символ +/- (десятичный код 177 в кодовой странице Windows-1252).

Когда я запрашиваю таблицу непосредственно в SQL Server Management Studio, я получаю символ тарабарщины вместо символа +/- в этой строке. Когда я использую эту таблицу в качестве источника в пакете SSIS, таблица назначения (которая использует типичную сортировку SQL_Latin1_General_CP1_CI_AS) заканчивается правильным символом +/-.

Теперь мне нужно создать механизм, который напрямую запрашивает исходную таблицу без SSIS. Как мне это сделать таким образом, что я получаю правильный символ вместо тарабарщины? Мое предположение было бы в том, что мне нужно было бы преобразовать/бросить столбец в сопоставление SQL_Latin1_General_CP1_CI_AS, но это не работает, поскольку я продолжаю получать символ тарабарщины.

Я пробовал следующее без везения:

select 
columnName collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
cast (columnName as varchar(100)) collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
convert (varchar, columnName) collate SQL_Latin1_General_CP1_CI_AS
from tableName

Что я делаю неправильно?

Ответы

Ответ 1

Преобразование набора символов выполняется неявно на уровне подключения к базе данных. Вы можете принудительно отключить автоматическое преобразование в строке подключения ODBC или ADODB с параметром "Auto Translate = False". Это НЕ рекомендуется. См.: https://msdn.microsoft.com/en-us/library/ms130822.aspx

В SQL Server 2005 произошла несовместимость кодовых страниц, когда кодовая страница базы данных и клиента не совпала. https://support.microsoft.com/kb/KbView/904803

Консоль управления SQL 2008 и выше - это приложение UNICODE. Все введенные или запрошенные значения интерпретируются как таковые на уровне приложения. Разговор между сопоставлением столбцов и из него выполняется неявно. Вы можете проверить это с помощью:

SELECT CAST(N'±' as varbinary(10)) AS Result

Это вернет 0xB100, который является символом Unicode U + 00B1 (как указано в окне консоли управления). Вы не можете отключить "Автоматический перевод" для Management Studio.

Если вы укажете другую сортировку в выборе, вы, в конечном итоге, получите двойное преобразование (с возможной потерей данных) до тех пор, пока "Автоматический перевод" все еще активен. Первоначальный символ сначала преобразуется в новую сортировку во время выбора, которая, в свою очередь, получает "Auto Translated" в "правильную" кодовую страницу приложения. Вот почему ваши различные тесты COLLATION по-прежнему показывают одинаковый результат.

Вы можете проверить, имеет ли эффект сортировки DOES выбор в случае выбора VARBINARY вместо VARCHAR, поэтому преобразование SQL Server не будет аннулировано клиентом до его представления:

SELECT cast(columnName COLLATE SQL_Latin1_General_CP850_BIN2 as varbinary(10)) from tableName
SELECT cast(columnName COLLATE SQL_Latin1_General_CP1_CI_AS as varbinary(10)) from tableName

Это даст вам 0xF1 или 0xB1 соответственно, если columnName содержит только символ '±'

Вы все равно можете получить правильный результат и, тем не менее, неправильный символ, если используемый вами шрифт не предоставляет правильный глиф.

Пожалуйста, дважды проверьте фактическое внутреннее представление вашего символа, отвечая запрос VARBINARY на правильный образец и проверяя, действительно ли этот код соответствует сортировке заданной базы данных SQL_Latin1_General_CP850_BIN2

SELECT CAST(columnName as varbinary(10)) from tableName

Различия в сопоставлении приложений и сопоставлении базы данных могут остаться незамеченными, если преобразование всегда выполняется одинаково. Проблемы возникают, как только вы добавляете клиента с другой сортировкой. Затем вы можете обнаружить, что внутреннее преобразование не может правильно соответствовать символам.

Все, что сказано, вы должны иметь в виду, что Management Studio обычно не является окончательной ссылкой при интерпретации наборов результатов. Даже если это выглядит тарабарщиной в MS, это все равно может быть правильным выходом. Вопрос в том, правильно ли отображаются записи в ваших приложениях.

Ответ 3

Нам может понадобиться дополнительная информация. Вот что я сделал для воспроизведения на SQL Server 2008:

CREATE DATABASE [Test] ON  PRIMARY 
    ( 
    NAME = N'Test'
    , FILENAME = N'...Test.mdf' 
    , SIZE = 3072KB 
    , FILEGROWTH = 1024KB 
    )
    LOG ON 
    ( 
    NAME = N'Test_log'
    , FILENAME = N'...Test_log.ldf' 
    , SIZE = 1024KB 
    , FILEGROWTH = 10%
    )
    COLLATE SQL_Latin1_General_CP850_BIN2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[MyTable]
    (
    [SomeCol] [varchar](50) NULL
    ) ON [PRIMARY]
GO
Insert MyTable( SomeCol )
Select '±' Collate SQL_Latin1_General_CP1_CI_AS
GO
Select SomeCol, SomeCol Collate SQL_Latin1_General_CP1_CI_AS
From MyTable

Результаты показывают исходный символ. Объявление сортировки в запросе должно возвращать правильный символ с точки зрения SQL Server, однако может быть, что слой представления затем преобразуется в нечто еще похожее на UTF-8.

Ответ 4

попробовать:

SELECT CAST( CAST([field] AS VARBINARY) AS varchar)