Не удалось вернуть запрос тайских данных

У меня есть таблица со столбцами, которые содержат как тайские, так и английские текстовые данные. НВАРЧАР(255). В SSMS я могу запросить таблицу и достаточно легко вернуть все строки. Но если я затем запрошу конкретно один из тайских результатов, он не вернет строк.

SELECT TOP 1000 [Province]
,[District]
,[SubDistrict]
,[Branch ]
FROM [THDocuworldRego].[dbo].[allDistricsBranches]

Возвращает

Province    District    SubDistrict Branch 
อุตรดิตถ์   ลับแล   ศรีพนมมาศ   Northern
Bangkok  Khlong Toei    Khlong Tan  SSS1

Но этот запрос:

SELECT [Province]
      ,[District]
      ,[SubDistrict]
      ,[Branch ]
  FROM [THDocuworldRego].[dbo].[allDistricsBranches]
  where [Province] LIKE 'อุตรดิตถ์'

Не возвращает строк. Что мне нужно сделать, чтобы получить ожидаемые результаты. Набор параметров сортировки — Latin1_General_CI_AS. Данные отображаются и вставляются без ошибок, просто не могу найти.


person Hammertime    schedule 14.10.2014    source источник
comment
Нет, это все еще ничего не возвращает. Требуется префикс N, как показано ниже   -  person Hammertime    schedule 14.10.2014
comment
@g2server: нет необходимости в RTRIM(). Это просто делает недействительными любые индексы в этом поле, которые не используются для помощи в этом запросе. Конечно, с предложением LIKE, начинающимся с %, в любом случае не будет использоваться индекс для этого поля, но, тем не менее, здесь нет никакой выгоды от использования RTRIM.   -  person Solomon Rutzky    schedule 14.10.2014
comment
Всем привет. Я понимаю, что прошло около 4 лет, но за это время я многому научился, поэтому я просто обновил свой ответ, чтобы он был более точным и подробным, если вам интересно :-).   -  person Solomon Rutzky    schedule 21.06.2018


Ответы (2)


Две проблемы:

  1. Строка, передаваемая в предложение LIKE, имеет вид VARCHAR из-за того, что перед ней не стоит заглавная буква «N». Например:

    SELECT 'อุตรดิตถ์' AS [VARCHAR], N'อุตรดิตถ์' AS [NVARCHAR]
    -- ?????????        อุตรดิตถ
    

    Здесь происходит следующее: когда SQL Server анализирует пакет запросов, ему необходимо определить точный тип и значение всех литералов/констант. Таким образом, он вычисляет, что 12 — это INT, а 12.0 — это NUMERIC и т. д. Он знает, что N'ดิ' — это NVARCHAR, который является всеобъемлющим набором символов, поэтому он принимает значение как есть. НО, как отмечалось ранее, 'ดิ' — это VARCHAR, что является 8-битной кодировкой, что означает, что набор символов контролируется кодовой страницей. Для строковых литералов и переменных/параметров кодовая страница, используемая для VARCHAR данных, является сопоставлением базы данных по умолчанию. Если в строке есть символы, недоступные на кодовой странице, используемой сопоставлением базы данных по умолчанию, они либо преобразуются в сопоставление «наилучшего соответствия», если такое сопоставление существует, либо становятся символом замены по умолчанию: ?.

    С технической точки зрения, поскольку сопоставление базы данных по умолчанию управляет строковыми литералами (и переменными) и поскольку существует кодовая страница для «тайского языка» (доступная в сопоставлениях Windows), то можно было бы иметь строку VARCHAR, содержащую тайские символы (что означает: 'ดิ', без префикса "N", будет работать). Но это потребует изменения сортировки базы данных по умолчанию, и это НАМНОГО больше работы, чем просто префикс строкового литерала с «N».

    Подробный обзор этого поведения см. в моей серии из двух частей:

  2. Вам нужно добавить подстановочные знаки с обоих концов:
    N'%อุตรดิตถ์%'

Конечный результат будет выглядеть так:

WHERE [Province] LIKE N'%อุตรดิตถ์%'

EDIT:
Я только что отредактировал вопрос, чтобы отформатировать «результаты», чтобы они были более удобочитаемыми. Теперь кажется, что следующее может также работать (поскольку в предикате LIKE в вопросе не используются подстановочные знаки):

WHERE [Province] = N'อุตรดิตถ์'

EDIT 2:
Строка (то есть что-то внутри одинарных кавычек) равна VARCHAR, если перед строковым литералом нет префикса "N". Тип данных назначения не имеет значения (например, столбец NVARCHAR(255)). Проблема здесь заключается в типе данных source, и этот источник является строковым литералом. И в отличие от string в .NET, SQL Server обрабатывает 'string' как 8-битную кодировку (VARCHAR; значения ASCII 0–127 одинаковы для всех кодовых страниц, расширенные значения ASCII 128–255, определяемые кодовой страницей, и, возможно, 2-байтовые последовательности для двухбайтовых наборов символов) и N'string' как UTF-16 Little Endian (NVARCHAR; набор символов Unicode, 2-байтовые последовательности для символов BMP от 0 до 65535, две 2-байтовые последовательности для кодовых точек выше 65535). Использование 'string' аналогично передаче переменной VARCHAR. Например:

DECLARE @ASCII VARCHAR(20);
SET @ASCII = N'อุตรดิตถ์';
SELECT @ASCII AS [ImplicitlyConverted]
-- ?????????
person Solomon Rutzky    schedule 14.10.2014
comment
Использование префикса N работало в запросе, но зачем он нужен, если столбец уже определен как nvarcahr(255). Зачем нужно переквалифицировать запрос? - person Hammertime; 14.10.2014
comment
@Hammertime: вы не переквалифицировали запрос. Я добавлю обновление в свой ответ, объясняющее это. - person Solomon Rutzky; 14.10.2014
comment
Спасибо за объяснение. Теперь я понимаю более полно. - person Hammertime; 17.10.2014
comment
@Hammertime Добро пожаловать. Если это сработало для вас, не могли бы вы принять этот ответ? - person Solomon Rutzky; 20.10.2014

Может быть несколько вещей!

Сначала распечатайте значение столбца и строку запроса в шестнадцатеричном формате.

SELECT     convert(varbinary(20)Province) as stored convert(varbinary(20),'อุตรดิตถ์') as query from allDistricsBranches;

Это должно дать вам некоторое представление о проблеме. Я думаю, что наиболее вероятной причиной является ввод символов ั, ิ в неправильной последовательности. Они отображаются как часть основной буквы, но хранятся внутри как отдельные символы.

person James Anderson    schedule 14.10.2014
comment
'hex' не является распознаваемым именем встроенной функции. - person Hammertime; 14.10.2014
comment
@Hammertime: правильно, HEX не является функцией T-SQL. Функция CONVERT используется для выполнения операций такого типа в SQL Server. - person Solomon Rutzky; 14.10.2014
comment
Использована правильная функция -- convert() вместо hex() - person James Anderson; 15.10.2014