Проблема с кодировкой столбца SQL Server VARCHAR, полученного в Python

10

Недавно у нас была проблема с кодировкой, связанной с полем, которое хранится в SQL Server как varchar (120). В SSMS varchar выглядит как:

"Кто убил JonBen? T?"

Тем не менее, когда он введен в Python, он выглядит так:

введите описание изображения здесь

Я исследовал это со стороны Python, и ничего странного не происходит. Моя теория состоит в том, что varchar в SQL Server принимает символы UTF-8, которые отображаются в python иначе, чем в SSMS. Я не очень знаком с кодированием в SQL Server. Может кто-нибудь, пожалуйста, дайте мне знать следующее:

  • Есть ли способ в SSMS для просмотра кодировки varchar? Например, см. \ X82 вместо отображения запятой, как это в настоящее время от SSMS?
  • Мы используем SQL Server 2008. Есть ли способ изменить кодировку для любых символов UTF-8 на символы ASCII без использования инструментов импорта / экспорта или выгрузки в плоский файл? Т.е. я могу сделать это преобразование через запрос?
  • Есть ли какой-либо способ программно идентифицировать проблемные записи с помощью запроса (проблемный определяется как символы UTF-8, которые не поддерживаются через ASCII)?

Заранее спасибо!

Использование sp_help N'table_name';я обнаружил , что Упорядочение этого VARCHARстолбца: SQL_Latin1_General_CP1_CI_AS.

Эрик
источник
Какой Collation использует этот VARCHARстолбец?
Соломон Руцкий,
@SolomonRutzky как вы проверяете параметры сортировки? Я не уверен, что это вообще значит
Эрик,
Самый быстрый способ я думаю: sp_help N'table_name';. Посмотрите на столбец на основе «name», а затем посмотрите на столбец «collation_name».
Соломон Руцкий,
@SolomonRutzky сопоставление для этого поля: «SQL_Latin1_General_CP1_CI_AS»
Эрик,

Ответы:

17

SQL Server не хранит UTF-8 ни при каких обстоятельствах. Вы получаете либо UTF-16 Little Endian (LE) через NVARCHAR(включая NCHARи NTEXT, но никогда не используете NTEXT) и XML, или некоторое 8-битное кодирование, основанное на кодовой странице, через VARCHAR(включая CHARи TEXT, но никогда не используете TEXT) ,

Проблема в том, что ваш код неправильно переводит этот символ 0x82, думая, что это UTF-8, но это не так. Не существует «символа» UTF-8, имеющего значение 0x82, поэтому вы получаете «неизвестный» / заменяющий символ « ». Пожалуйста, смотрите следующую таблицу UTF-8, которая показывает, что для однобайтового 0x82 нет символа:

Таблица кодировки UTF-8

Как указано в OP, сопоставление рассматриваемого столбца таково SQL_Latin1_General_CP1_CI_AS, что означает, что 8-разрядное кодирование использует кодовую страницу 1252, то есть Windows Latin 1 (ANSI) . И проверка того, что эта диаграмма (прокрутите вниз до нижней диаграммы, поскольку она имеет имена символов), значение 0x82 (ищите «82» в столбце «Кодовая точка»), на самом деле является единственной кавычкой Low-9, которую вы видите в SSMS. Этот символ в UTF-8, представляет собой последовательность 3 байт: E2 80 9A.

Все это означает: ваш код Python должен либо установить кодировку клиента для соединения с SQL Server на кодовую страницу 1252, либо вам нужно изменить / преобразовать кодировку возвращаемой строки из кодовой страницы 1252 в UTF-8.

Конечно, если это отображается на веб-странице, вы можете изменить объявленный кодировку страницы Windows-1252, но это может помешать другим символам на странице, если там уже есть символы UTF-8.

Соломон Руцкий
источник
Хорошо, это очень полезно, спасибо Соломон. Пожалуйста, дайте мне знать о неправильном переводе. Это довольно сложный вопрос, и я даже не знаю, с чего начать.
Eric
Вау, удивительная деталь, @Solomon! Я приземлился здесь в поисках другой проблемы с Python + MS SQL, но продолжал читать, потому что я очень много учился. :-P
Майк Уильямсон
1
@MikeWilliamson Спасибо, что поделились этим комплиментом :). Вы также можете быть заинтересованы в следующем: TSQL-хэш md5, отличный от C # .NET md5 (на SO), как вырезать еврейские акцентные метки (здесь на DBA.SE) и Collations.Info . Наслаждайтесь!
Соломон Руцкий
Спасибо! Я подозреваю, что любой, кто работает с языком, не основанным на латинице, знает этот материал гораздо лучше, чем любой из нас, кто блаженно работает в США / Великобритании. :)
Майк Уильямсон,
1
Просто примечание: MS SQL Server 2019 представляет встроенную поддержку UTF-8 в типах данных VARCHAR / CHAR.
Григорий