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

问题描述 投票:0回答:4

Sqlite3 默认情况下仅按 ascii 字母排序。我尝试在谷歌中查找,但我发现的唯一内容是有关排序规则的信息。 Sqlite3 仅具有

NOCASE
RTRIM
BIARY
排序规则。如何添加对特定区域设置的支持? (我在 Rails 应用程序中使用它)

ruby-on-rails sqlite locale collation
4个回答
29
投票

我接受了Doug Currie的回答,但我想添加一些“算法”如何做到这一点,因为sqlite3文档非常奇怪(至少对我来说)。

好的,我们已经可以使用 sqlite3 了,现在:

  1. 下载 sqlite 的 ICU 扩展

  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. 创建新排序规则:

    选择 icu_load_collation('pl_PL', 'POLISH');
    

    第一个参数是所需的语言环境,第二个参数是它的语言环境(可以是任何语言)。

  5. 现在我们可以使用新的语言环境对数据进行排序:

    SELECT * FROM some_table ORDER BY name COLLATE POLISH;
    

    而且不区分大小写!


13
投票

SQLite 支持ICU集成。根据自述文件,

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

3
投票

如果您无力编译 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');

我并不期望这种方法与本机扩展一样高效,但它肯定更便携。


1
投票

正如 Doug Currie 回答的那样,可以通过加载 SQLite“ICU”扩展来启用正确排序重音字符

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

libicu.so
代替。

这就是我在 Ubuntu 16.04 和 Debian 9.8 Stretch 上的工作:

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 -fPIC -shared icu.c `icu-config --ldflags` -o libicu.so
sudo cp libicu.so /usr/local/lib/
sudo ldconfig

更新:在以后的版本中,

icu-config
不再可用,因此请使用
pkg-config
代替。这在 Debian 11“bullseye”中有效:

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

之后在sqlite3中,就可以了

.load libicu
SELECT icu_load_collation('', 'ICU');

icu_load_collation
的 2 个参数是区域设置和自定义名称。区域设置似乎是可选的,可以留空。然后可以通过

看到自定义名称
PRAGMA collation_list;

它可以像

一样使用
SELECT col FROM tbl ORDER BY col COLLATE ICU;
© www.soinside.com 2019 - 2024. All rights reserved.