Sqlite3 默认情况下仅按 ascii 字母排序。我尝试在谷歌中查找,但我发现的唯一内容是有关排序规则的信息。 Sqlite3 仅具有
NOCASE
、RTRIM
和 BIARY
排序规则。如何添加对特定区域设置的支持?
(我在 Rails 应用程序中使用它)
我接受了Doug Currie的回答,但我想添加一些“算法”如何做到这一点,因为sqlite3文档非常奇怪(至少对我来说)。
好的,我们已经可以使用 sqlite3 了,现在:
编译:
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
到编译选项,这很有帮助。运行sqlite3。我们可以使用命令加载扩展:
.load './libSqliteIcu.so'
假设在当前目录,我们也可以指定整个路径。
创建新排序规则:
选择 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');
我并不期望这种方法与本机扩展一样高效,但它肯定更便携。
正如 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;