Символы Юникода, вызывающие проблемы при сравнении строк в SQL Server 2005 - PullRequest
4 голосов
/ 16 февраля 2010

Этот запрос:

select *
from op.tag
where tag = 'fussball'

Возвращает результат со значением столбца тега "fußball". Столбец «tag» определяется как nvarchar (150).

Хотя я понимаю, что они грамматически похожи , кто-нибудь может объяснить и защитить это поведение? Я предполагаю, что это связано с теми же настройками сортировки, которые позволяют изменять чувствительность к регистру столбца / таблицы, но кому это нужно? Уникальное ограничение на столбец также вызывает сбой при вставке одного значения, когда другое существует из-за нарушения ограничения. Как мне это отключить?

Вопрос о дополнительном бонусном балле. Объясните, почему этот запрос не возвращает никаких строк:

select 1 
where 'fußball' = 'fussball'

Бонусный вопрос (ответ?): @ScottCher лично указал мне, что это происходит из-за строкового литерала "fussball", рассматриваемого как varchar. Этот запрос возвращает результат:

select 1 
where 'fußball' = cast('fussball' as nvarchar)

Но опять же, этот не делает:

select 1 
where cast('fußball' as varchar) = cast('fussball' as varchar)

Я в замешательстве.

Ответы [ 5 ]

3 голосов
/ 16 февраля 2010

Я полагаю, набор параметров Unicode для вашего соединения / таблицы / базы данных указывает, что ss == ß. Последнее поведение может быть связано с тем, что он находится на неверном быстром пути, или, может быть, он выполняет двоичное сравнение, или, возможно, вы не передаете ß в правильной кодировке (я согласен, что это глупо).

http://unicode.org/reports/tr10/#Searching упоминает, что U + 00DF имеет специальный случай. Вот проницательный отрывок:

Язык чувствительный поиск и соответствия тесно связаны с сверка. Строки, которые сравниваются как равны на каком-то уровне прочности те это должно соответствовать при выполнении соответствие с учетом языка. За Например, в первичной силе, "ß" будет соответствовать «сс» в соответствии с UCA, и «аа» будет соответствовать «å» в Датский пошив УЦА.

1 голос
/ 17 февраля 2010

Бонусный вопрос (ответ?): @ScottCher указал мне в частном порядке, что это из-за строкового литерала "Суета" рассматривается как varchar. Этот запрос возвращает результат:

select 1 where 'fußball' = cast('fussball' as nvarchar)

Здесь вы имеете дело с правилами приоритета типов данных SQL Server, как указано в Тип данных приоритетов . Сравнения всегда выполняются с использованием типа с более высоким приоритетом:

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

Поскольку nvarchar имеет более высокий приоритет, чем varchar, сравнение в вашем примере будет происходить в соответствии с типом nvarchar, поэтому он действительно точно такой же, как и select 1 where N'fußball' =N'fussball' (то есть с использованием типов Unicode). Я надеюсь, это также проясняет, почему ваш последний случай не возвращает ни одной строки.

1 голос
/ 17 февраля 2010

Это не ответ, который объясняет поведение, но может иметь значение:

В этом вопросе я узнал, что с использованием сопоставления

Latin1_General_Bin 

позволит избежать большинства недостатков сопоставления.

1 голос
/ 16 февраля 2010

Некоторые ответы помощника - не полный ответ на ваш вопрос, но все же может быть полезным:

Если вы попробуете:

SELECT 1 WHERE N'fußball' = N'fussball'  

вы получите «1» - при использовании «N» для обозначения Unicode две строки считаются одинаковыми - почему это так, я пока не знаю.

Чтобы найти стандартное сопоставление для сервера, используйте

SELECT SERVERPROPERTY('Collation')

Чтобы найти сопоставление данного столбца в базе данных, используйте этот запрос:

SELECT
  name 'Column Name', 
  OBJECT_NAME(object_id) 'Table Name', 
  collation_name
FROM sys.columns
WHERE object_ID = object_ID('your-table-name') 
AND name = 'your-column-name'
1 голос
/ 16 февраля 2010

SELECT возвращает возвращает строку с сопоставлением Latin1_General_CI_AS (SQL2000).

Это не с сопоставлением Latin1_General_BIN.

Вы можете присвоить столбцу таблицы параметры сортировки, используя ключевое слово COLLATE после N / VARCHAR.

Вы также можете сравнивать строки с определенным сопоставлением, используя синтаксис

string1 = string2 COLLATE < collation >
...