2010-02-16 4 views
4

Этот запрос:Unicode символы, вызывающие проблемы в SQL Server 2005 строки сравнения

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

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

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

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

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

Bonus вопрос (ответ): @ScottCher указал мне в частном порядке, что это связано с строковый литерал «Fußball», которое лечат, как VARCHAR. Этот запрос ДЕЛАЕТ возвращает результат:

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

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

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

Я запутался.

+0

Какое сравнение вы используете на своем SQL Server? Какие языки и языковые настройки вы используете? –

+0

@marc_s все по умолчанию установка в США. Я думаю, что это Latin1_General_CS_AS? – TheSoftwareJedi

+0

Значение по умолчанию для @marc_s по умолчанию равно SQL_Latin1_General_CP1_CI_AS. Возможно, этот сервер был обновлен с Sql Server 2000. Тем не менее, все еще запутано это поведение! – TheSoftwareJedi

ответ

3

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

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

Язык чувствительного поиск и соответствия тесно связаны с обобщению. Строки, которые сравниваются как , равны на некотором уровне прочности, равны , которые должны быть сопоставлены при выполнении языкового соответствия. Например, при , «ß» будет соответствовать «ss» в соответствии с UCA, а «aa» будет соответствовать «å» в датском пошиве UCA .

+0

Спасибо! Я отредактировал, чтобы сделать более прямую ссылку, и процитировать соответствующий раздел статьи. – TheSoftwareJedi

1

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

Это не с сортировкой Latin1_General_BIN.

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

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

string1 = string2 COLLATE <collation> 
1

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

Если попробовать:

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

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

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

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

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

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

Latin1_General_Bin 

избежит большинства особенностей сортировки.

1

Bonus вопрос (ответ): @ScottCher указал мне в частном порядке, что это связано с строкового литерала «Fußball», которое лечат, как VARCHAR. Этот запрос НЕ возвращает результат:

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

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

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

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

Смежные вопросы