Проблема с кодировкой на SQL Server

Я работаю с базой данных SQL Server; кодировка экземпляра базы данных "SQL_Latin1_General_CP1_CI_AS".

Следующий код:

UPDATE ...
SET field = CHAR(136)
WHERE...

помещает в поле следующий символ: ˆ

Но! В кодовой таблице Latin1 коды 127-159 просто не определены! Как он вставляет этот символ?

И что еще более сбивает с толку, когда я читаю значение этого поля в строковую переменную на C# и преобразовываю его в char, я получаю код 710 вместо 136.

Я попытался использовать преобразование кодировки:

var latin1Encoding = Encoding.GetEncoding("iso-8859-1");
var test = latin1Encoding.GetBytes(field); // field is a string read from db

Но в этом случае я получаю код 94, который является ^ (выглядит похоже, но это не то же самое, и мне нужно точно такое же).


person Nat    schedule 25.10.2011    source источник
comment
Если вы хотите, чтобы все было точно так же, я думаю, вам следует использовать двоичную сортировку. Преобразование в другую кодировку всегда происходит с потерями.   -  person Todd Li    schedule 25.10.2011


Ответы (2)


Но! В кодовой таблице Latin1 коды 127-159 просто не определены!

В ISO-8859-1 определен символ 136, но это редко используемый и по большей части бессмысленный управляющий символ.

Но SQL_Latin1_General_CP1_CI_AS, несмотря на название «Latin1», не является ISO-8859-1. Это западноевропейская кодовая страница ANSI, 1252, которая похожа на ISO-8859-1, но имеет множество различных символов в диапазоне 128–159.

Символ 136 в кодовой странице 1252: U+02C6 MODIFIER LETTER CIRCUMFLEX ACCENT, ˆ; десятичное кодовое число 710.

в этом случае я получаю код 94, который ^

Да, вы запрашиваете преобразование в ISO-8859-1, который не включает символ U+02C6, поэтому вы получаете «наиболее подходящий запасной вариант», то есть символ, который немного похож на тот, который вы хотели . Обычно это плохо; многие из выбранных запасных вариантов весьма сомнительны. Вы можете изменить это поведение, например, с помощью EncoderFallback. вместо этого генерировать исключение.

person bobince    schedule 25.10.2011

Хорошо, здесь происходит несколько преобразований.

  1. Когда вы используете Char(136), число является кодом ASCII, но, поскольку число 136 находится за пределами стандартного набора ASCII, вы получаете символ, определенный Windows-1252. Этот символ является циркумфлексом.
  2. В дополнение к определению кодировки столбцов, отличных от Unicode, сопоставление также устанавливает некоторые правила для перевода между символами, отличными от Unicode, и символами Unicode при попытке сохранить символ, отличный от Unicode, в поле Unicode. Если преобразование не определено, вы, как правило, получаете ?, но в этом случае вы получаете символ с кодовой точкой Unicode U+02C6. Важно понимать, что сопоставление устанавливает эквивалентность между символами, потому что было решено, что они похожи/эквивалентны. Это не имеет ничего общего с реальными ценностями.
  3. Наконец, вы использовали кодировку iso-8859-1, чтобы получить числовой код циркумфлекса в той кодировке, которая равна 94.
person Steve Rowbotham    schedule 25.10.2011