如何使用指定的语言环境对sqlite3中的文本进行排序?

时间:2009-03-04 16:50:51

标签: ruby-on-rails sqlite locale collation

默认情况下,Sqlite3仅按ascii字母排序。我试图查看谷歌,但我发现的唯一的事情是有关整理的信息。 Sqlite3只有NOCASERTRIMBIARY个排序规则。如何添加对特定区域设置的支持? (我在Rails应用程序中使用它)

5 个答案:

答案 0 :(得分:25)

我接受了Doug Currie的回答,但我想添加一些“算法”怎么做,因为sqlite3文档非常奇怪(至少对我而言)。

好的,我们现在正在使用sqlite3:

  1. Download ICU extension for 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;
    

    它不区分大小写!

答案 1 :(得分:13)

SQLite supportsICU的集成。根据自述文件, sqlite/ext/icu/README.txt sqlite/ext/icu/目录包含SQLite“ICU”扩展的源代码,a 将“International Components for 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

答案 2 :(得分:1)

如果你负担不起编译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');

我不希望这种方法与原生扩展一样高效,但它肯定更具可移植性。

答案 3 :(得分:0)

对于那些无法自行构建扩展程序的人,我在这里提供了适用于macOS和Linux的编译版本:http://files.tempel.org/Various/Sqlite3ICUExtention

如果重要的话,适用于Intel 32位和64位的Linux版本都是在Ubuntu 16上构建的。

通常,您不应该信任其他人提供的已编译代码,但是我是一个公开的人,这意味着如果我提供“不良”版本,我将冒很大的风险。为确保服务器没有受到中间人攻击或黑客攻击,以下是这3个文件的MD5哈希值:

dbpedia

答案 4 :(得分:0)

正如道格·柯里(Doug Currie)回答的那样,可以通过加载SQLite "ICU" extension

来启用对重音字符的正确排序。

需要编译扩展名,如kiew自己的答案中所述。但是,ICU自述文件和kiew的答案中给出的库名对我不起作用。 This other answer建议改用名称old_id

这就是在Ubuntu 16.04和Debian 9.8 Stretch上对我有用的东西:

libicu.so

在sqlite3之后,您可以

sudo apt install libicu-dev libsqlite3-dev dpkg-dev gcc make
apt-get source sqlite3
cd sqlite3-*/ext/icu       # assuming you have only 1 sqlite3 source directory
gcc -shared icu.c `icu-config --ldflags` -fPIC -o libicu.so
sudo cp libicu.so /usr/local/lib/
sudo ldconfig

.load libicu SELECT icu_load_collation('', 'ICU'); 的2个参数是语言环境和自定义名称。语言环境似乎是可选的,可以保留为空。然后可以使用

看到自定义名称
icu_load_collation

它可以用作

PRAGMA collation_list;