порядок без учета регистра в SQLite в .net

Я использую SQLite из программы C# с помощью SQLite.net ( http://sqlite.phxsoftware.com ) .

По умолчанию SQLite выбирает порядок по предложению, сортировка чувствительна к регистру, я хочу, чтобы результат сортировался без учета регистра, я нашел «COLLATE NOCASE», но в документации говорится, что он будет обрабатывать только английские символы в диапазоне ascii, я хочу истинную лингвистическую международную сортировку без учета регистра используя сопоставление CultureInfo.CurrentCulture (используя String.Compare, это поможет).


person Nir    schedule 27.05.2009    source источник


Ответы (5)


Я считаю, что такая сортировка не предусмотрена в текущих версиях SQLite. Таким образом, кажется, что наиболее разумным планом является удаление сортировки из запроса и последующая сортировка в чистом .Net, где у вас есть полный контроль и доступ к таким конструкциям, как информация о культуре потока.

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

SQLite 3 позволяет определять пользовательские функции сопоставления, и их можно выполнять в SQLite.Net как функции .net, но накладные расходы на вызовы туда и обратно через управляемую/неуправляемую границу значительны. Вот один человек пытается сделать это на С++. Если у вас нет доступа к чьей-либо хорошо протестированной и стабильной сортировке с учетом культуры Unicode в C++, я предлагаю придерживаться простого подхода сортировки, где это возможно.

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

[SQLiteFunction(Name = "CULTURESORT", FuncType = FunctionType.Collation)]
class CultureSort : SQLiteFunction
{
    public override int Compare(string param1, string param2)
    {
        return String.Compare(
            param1,param2, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)
        );
    }
}

Постскриптум, если хотите пофантазировать: есть благословенная сборка SQLite, которая интегрирует библиотеку ICU для "правильной" поддержки юникода при упорядочении/подобном/верхнем/нижнем, но вам нужно будет интегрировать это в код sqlite, используемый в качестве поддержки для оболочки .Net. Это многим непросто.

person ShuggyCoUk    schedule 27.05.2009

SQLite.NET позволяет вам определять пользовательские функции на C#, которые вы можете использовать в запросах SQL. Таким образом, должна быть возможность написать функцию custom_upper или custom_lower на С#, которая будет обрабатывать преобразование регистра с текущим сопоставлением культуры...

person Thomas Levesque    schedule 27.05.2009

Да, это гораздо сложнее, чем вы думаете. В некоторых культурах правила другие, и без знания того, на какой культуре вы хотите основываться, становится невозможным. Рассмотрим известный (среди 18n человек) пример турецкого.

person JasonRShaver    schedule 27.05.2009

Вы можете просто использовать функцию lower() sqlite:

select * from data order by lower(name)
person njzk2    schedule 11.10.2011
comment
правильный способ - выбрать * из порядка данных по нижнему (имени), имени - person Vladimir Stazhilov; 15.02.2012
comment
SQLite lower() имеет ту же проблему, что и ORDER BY - работает только для ASCII. Вы должны написать свою собственную функцию, см. следующий ответ stackoverflow.com/a/918234/254109 - person xmedeko; 05.02.2016

Вы можете использовать метод ToLower() для получения быстрого результата:

return model.Users.OrderBy(u => u.Name.ToLower()).ToList();
person Rover    schedule 22.11.2010
comment
слишком медленно) преобразование всей строки только для использования первых нескольких символов - person Ivan G.; 02.04.2012
comment
Вы пробовали? Преобразование происходит на стороне SQL. - person Rover; 03.04.2012
comment
да. Я не думаю, что msil интерпретируется по-разному с обеих сторон. - person Ivan G.; 03.04.2012