5

アクセントや大文字と小文字を気にせずに、SQLite DB で 2 つの文字列を比較したいと考えています。つまり、「Événement」は「evenèment」と等しいはずです。

Debian Wheezy では、SQLite パッケージは ICU を提供しません。そこで、ICU モジュールを含む公式の SQLite パッケージ (バージョン 3.7.15.2 2013-01-09 11:53:05) をコンパイルしました。現在、より優れた Unicode サポートがあります (元lower()は ASCII 文字のみに適用されていましたが、現在は他の文字にも対応しています)。しかし、比較に照合を適用することはできません。

SELECT icu_load_collation('fr_FR', 'FRENCH');
SELECT 'événement' COLLATE FRENCH = 'evenement';
-- 0 (should be 1)
SELECT 'Événement' COLLATE FRENCH = 'événement';
-- 0 (should be 1 if collation was case-insensitive)
SELECT lower('Événement') = 'événement';
-- 1 (at least lower() works as expected with Unicode strings)

SQLiteのドキュメントでは、これが照合を適用する正しい方法であることが確認されています。この ICU 拡張機能のドキュメントは少し軽いと思います(例が少なく、照合順序の大文字と小文字の区別については何もありません)。

COLLATE上記の例で演算子が効果がない理由がわかりません。助けてください。

4

1 に答える 1

6

私は状況を理解するのに何時間もかかりました...SQLiteでICU照合が定義される方法は、比較に(ほとんど)発生しません。例外は、ICUによると、カンチレーションマークの付いたヘブライ語のテキストです。これは、ICUライブラリの照合のデフォルトの動作です。SQLiteでは、LIKEICUがロードされると大文字と小文字が区別されなくなりますが、強調文字の正規化はこの方法では実現できません。

最終的に、必要なのは 、照合 の強度を デフォルトの3次レベルではなく1次レベルに設定することであることがわかりました。

ロケールを介してこれを設定する方法が見つかりませんでした(たとえば、のいくつかのバリアントSELECT icu_load_collation('fr_FR,strength=0', 'french')は役に立たなかった)。したがって、唯一の解決策はSQLiteのコードにパッチを適用することでした。ICUAPIucol_setStrength()の機能のおかげで簡単でした。

最小限の変更は1行のパッチです。関数のucol_setStrength(pUCollator, 0);後に行を追加します。下位互換性のある変更のために、強度を設定するオプションの3番目のパラメーターを追加しました。デフォルトの場合は0、プライマリの場合は1、4クォーターまでです。差分を参照してください。pUCollator = ucol_open(zLocale, &status);icuLoadCollation()icu_load_collation()

ついに私は私が欲しかったものを手に入れました:

SELECT icu_load_collation('fr_FR', 'french_ci', 1); -- collation with strength=primary
SELECT 'Événement' COLLATE french_ci = 'evenèment';
-- 1
于 2013-02-25T10:12:50.007 に答える