Как отсортировать текст в sqlite3 с указанным языком?

StackOverflow https://stackoverflow.com/questions/611459

Вопрос

Sqlite3 по умолчанию сортирует только по буквам ascii. Я попытался заглянуть в Google, но единственное, что я нашел, это информация о сопоставлениях. Sqlite3 имеет только сопоставления NOCASE , RTRIM и BIARY . Как добавить поддержку для конкретной локали? (Я использую его в приложении Rails)

Это было полезно?

Решение

SQLite поддерживает интеграцию с ICU . Согласно файлу Readme, <Код> SQLite / внутр / СИС / README.txt каталог sqlite / ext / icu / содержит исходный код SQLite " ICU " расширение, интеграция «Международные компоненты для Unicode» библиотека с SQLite.

1. Features

    1.1  SQL Scalars upper() and lower()
    1.2  Unicode Aware LIKE Operator
    1.3  ICU Collation Sequences
    1.4  SQL REGEXP Operator

Другие советы

Я принял ответ Дуга Карри, но хочу добавить некоторый "алгоритм" как это сделать, потому что документация sqlite3 очень странная (по крайней мере для меня).

Хорошо, у нас есть работающий sqlite3 и теперь:

<Ол>
  • Загрузить расширение ICU для sqlite

  • Скомпилируйте его:

    gcc -shared icu.c `icu-config --ldflags` -o libSqliteIcu.so
    

    Это для Linux. Мне также нужно было установить дополнительный пакет разработки ICU:

    sudo apt-get install libicu-dev
    

    Я работаю над 64-битной архитектурой и получаю сообщение об ошибке с __location R_X86_64_32S __ (что бы это ни значило :). GCC предложил добавить -fPIC для компиляции параметров, и это помогло.

  • Запустите sqlite3. Мы можем загрузить расширение командой:

    .load './libSqliteIcu.so'
    

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

  • Создать новое сопоставление:

    SELECT icu_load_collation('pl_PL', 'POLISH');
    

    Первый параметр - это требуемая локаль, а второй - это (может быть любым).

  • Теперь мы можем сортировать данные с помощью нашей новой локали:

    SELECT * FROM some_table ORDER BY name COLLATE POLISH;
    

    И это без учета регистра!

  • Если вы не можете позволить себе скомпилировать расширение ICU, вы можете сделать то же самое для UDF. В PHP / PDO:

    $pdo->sqliteCreateFunction('locale',
        function ($data, $locale = 'root')
        {
            static $collators = array();
    
            if (isset($collators[$locale]) !== true)
            {
                $collators[$locale] = new \Collator($locale);
            }
    
            return $collators[$locale]->getSortKey($data);
        }
    );
    

    Пример использования:

    SELECT * FROM "table" ORDER BY locale("column", 'pt_PT');
    

    Я не ожидаю, что этот подход будет столь же эффективным, как собственное расширение, но он, безусловно, более переносим.

    Для тех, кто не может создать расширение самостоятельно, я сделал скомпилированные версии для MacOS и Linux здесь: http://files.tempel.org/Various/Sqlite3ICUExtention

    Версии Linux для 32-разрядной и 64-разрядной систем Intel были построены на Ubuntu 16, если это имеет значение.

    Как правило, вы не должны доверять скомпилированному коду, предоставленному другими, но я довольно публичный человек, то есть я бы очень рисковал, если бы предоставил " плохой " версия. И чтобы убедиться, что на моем сервере не было ни атаки, ни взлома посредником, вот хеш MD5 для 3 файлов:

    libSqliteIcu-i386.so = 6decd73f27d9c61243128e798304508f
    libSqliteIcu-x86_64.so = b127c8a1f65503c91c61a21732eb11be
    sqlite3_icu_extension.dylib = a29d59f6b74e7ef234691729b82da660
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top