Подтвердить что ты не робот

String Сравнение различий между .NET и T-SQL?

В тестовом примере, который я написал, сравнение строк не работает одинаково между SQL Server/.NET CLR.

Этот код С#:

string lesser =  "SR2-A1-10-90";
string greater = "SR2-A1-100-10";

Debug.WriteLine(string.Compare("A","B"));
Debug.WriteLine(string.Compare(lesser, greater));

Будет выводиться:

-1
1

Этот код SQL Server:

declare @lesser varchar(20);
declare @greater varchar(20);

set @lesser =  'SR2-A1-10-90';
set @greater = 'SR2-A1-100-10';

IF @lesser < @greater
    SELECT 'Less Than';
ELSE
    SELECT 'Greater than';

Будет выводиться:

Less Than

Почему разница?

4b9b3361

Ответ 1

Это описанное здесь.

Коллажи Windows (например, Latin1_General_CI_AS) используют правила сортировки типа Unicode. SQL Collations нет.

Это приводит к тому, что символ дефиса обрабатывается по-разному между ними.

Ответ 2

В ответ на gbn вы можете заставить их вести себя одинаково с помощью CompareOptions.StringSort в С# (или с помощью StringComparison.Ordinal). Это рассматривает символы как встречающиеся перед буквенно-цифровыми символами, поэтому "-" < "0".

Однако Unicode vs ASCII ничего не объясняет, так как шестнадцатеричные коды кодовой страницы ASCII переводятся до кодовой страницы Unicode: "-" - 002D (45), а "0" - 0030 (48).

Что происходит, так это то, что .NET использует по умолчанию "лингвистическую" сортировку, основанную на порядковом упорядочении и весе, применяемом к различным символам указанной или текущей культурой. Этот лингвистический алгоритм позволяет, например, "резюме" (пишется с акцентами) появляться сразу после "возобновления" (записанного без акцентов) в отсортированном списке слов, так как "é" получает дробный порядок сразу после "e" и задолго до "f". Это также позволяет тесно взаимодействовать "сотрудничество" и "сотрудничество", поскольку символу штриха присваивается низкий "вес"; это имеет значение только как абсолютные окончательные тай-брейки при сортировке слов типа "бит", "бит" и "бит-сдвиг" (которые появятся в этом порядке).

Так называемая порядковая сортировка (строго согласно значениям Юникода, с или без учета нечувствительности к регистру) будет давать очень разные и иногда нелогичные результаты, поскольку варианты букв обычно появляются после основного неаполяризованного латинского алфавита в ординалах ASCII/Unicode, тогда как перед ним появляются символы. Например, "é" приходит после "z", и поэтому слова "резюме" , "канифоль", "рубль", "резюме" будут сортироваться в этом порядке. "Бит", "Бит-сдвиг", "Битер", "Биты" будут сортироваться в этом порядке, поскольку сначала будет апостроф, затем тире, затем буквой "е", затем буквой "с". Ни один из них не кажется логичным с точки зрения "естественного языка".

Ответ 3

  • В SQL вы использовали varchar, который в основном ASCII (с учетом сортировки), который даст - до 0
  • В С# все строки являются Unicode

Более тонкие точки UTF-xx (С#) и UCS-2 (SQL Server) довольно сложны.

Edit:

Я отправил слишком скоро

Я получаю "Больше" на SQL Server 2008 с помощью сопоставления Latin1_General_CI_AS

Изменить 2:

Я также попробую SELECT ASCII(...) на тире. Например, если фрагмент SQL когда-либо был в документе Word, то - (150) не является - (45), который я скопировал в SQL Server для проверки моего браузера из ваших вопросов. См. CP 1252 (= CP1 = SQL Server lingo)

Изменить 3: См. ответ Мартина Смита: 2 сортировки имеют разные порядки сортировки.

Ответ 4

Несколько отличных ответов уже на то, почему это происходит, но я уверен, что другие просто хотят знать код С# для итерации коллекции в том же порядке, что и SQL-сервер. Я нашел следующие работы лучше всего. "Ordinal" обходит проблему с дефисом, в то время как "IgnoreCase", по-видимому, отражает и SQL-сервер.

Debug.WriteLine(string.Compare(lesser, greater, StringComparison.OrdinalIgnoreCase));