【问题标题】:How to sort text in sqlite3 with specified locale?如何使用指定的语言环境对 sqlite3 中的文本进行排序?
【发布时间】:2010-10-11 07:40:49
【问题描述】:

默认情况下,Sqlite3 仅按 ascii 字母排序。我试图在谷歌中查找,但我发现的唯一内容是有关排序规则的信息。 Sqlite3 只有NOCASERTRIMBIARY 排序规则。如何添加对特定语言环境的支持? (我在 Rails 应用程序中使用它)

【问题讨论】:

    标签: ruby-on-rails sqlite locale collation


    【解决方案1】:

    正如 Doug Currie 回答的那样,可以通过加载 SQLite "ICU" extension 来正确排序重音字符

    需要编译扩展,如 kiew 自己的回答中所述。但是,ICU 自述文件和 kiew 的回答中给出的库名称对我不起作用。 This other answer 建议改用名称 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 -shared icu.c `icu-config --ldflags` -fPIC -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;
    

    【讨论】:

      【解决方案2】:

      我接受了 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. 创建新的排序规则:

        选择 icu_load_collat​​ion('pl_PL', 'POLISH');

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

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

        SELECT * FROM some_table ORDER BY name COLLATE POLISH;

        而且不区分大小写!

      【讨论】:

      • 我未能在 macOS 10.13 上构建它。对于我可以谷歌搜索的所有文件,它们似乎都已经过时了。
      • 安装ICU和SQLite3开发包sudo apt update && sudo apt install libicu-dev libsqlite3-dev -y
      • 谢谢。这真的很有帮助,即使它没有立即起作用。 .load libSqliteIcu 会给Error: /usr/local/lib/libSqliteIcu.so: undefined symbol: sqlite3_sqliteicu_init。将名称更改为libicu.so 后,它可以工作。附加答案中的详细信息。
      【解决方案3】:

      SQLite supportsICU 集成。根据自述文件, 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
      

      【讨论】:

      • 第一个链接现在受密码保护。
      【解决方案4】:

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

      我不认为这种方法会像原生扩展一样高效,但它肯定更便携。

      【讨论】:

        猜你喜欢
        • 2018-12-17
        • 2012-09-06
        • 1970-01-01
        • 2023-03-26
        • 2012-06-22
        • 2011-05-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多