Как отсортировать текст в sqlite3 с указанным языком? - PullRequest
14 голосов
/ 04 марта 2009

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

Ответы [ 4 ]

25 голосов
/ 05 марта 2009

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

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

  1. Скачать расширение ICU для sqlite

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

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

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

    sudo apt-get install libicu-dev
    

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

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

    .load './libSqliteIcu.so'
    

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

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

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

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

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

    SELECT * FROM some_table ORDER BY name COLLATE POLISH;
    

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

13 голосов
/ 05 марта 2009

SQLite поддерживает интеграцию с ICU . Согласно файлу Readme, sqlite/ext/icu/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
1 голос
/ 02 сентября 2013

Если вы не можете позволить себе скомпилировать расширение 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');

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

0 голосов
/ 15 мая 2019

Для тех, кто не может собрать расширение самостоятельно, я сделал скомпилированные версии для 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
...