web-dev-qa-db-ja.com

SQLiteクエリでアクセントを無視する方法(Android)

私はAndroidの初心者で、SQLiteでクエリに取り組んでいます。私の問題は、文字列でアクセントを使用する場合です。

  • ÁÁÁ
  • ááá
  • ÀÀÀ
  • ààà
  • aaa
  • AAA

私が行った場合:

SELECT * FROM TB_MOVIE WHERE MOVIE_NAME LIKE '%a%' ORDER BY MOVIE_NAME;

それは戻ります:

  • AAA
  • aaa(他の人を無視しています)

しかし、私がそうするなら:

SELECT * FROM TB_MOVIE WHERE MOVIE_NAME LIKE '%à%' ORDER BY MOVIE_NAME;

それは戻ります:

  • ààà(タイトル「ÀÀÀ」を無視)

アクセントや大文字小文字を気にせずにSQLiteDBで文字列を選択したい。助けてください。

20
andrehsouza

一般に、SQLでの文字列の比較は、列または式のCOLLATEルールによって制御されます。 Androidでは、3つの照合シーケンスのみが 事前定義 :BINARY(デフォルト)、LOCALIZED、およびUNICODEです。それらのどれもあなたのユースケースに理想的ではなく、新しい照合関数をインストールするためのC APIは、残念ながらJava APIでは公開されていません。

これを回避するには:

  1. テーブルに別の列を追加します(例:MOVIE_NAME_ASCII
  2. アクセント記号を削除して、この列に値を格納します。文字列をUnicodeNormal Form D(NFD)に正規化し、非ASCIIコードポイントを削除することでアクセントを削除できます。NFDはアクセント付き文字を大まかにプレーンとして表すためASCII +アクセントマーカーの組み合わせ:

    String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
        .replaceAll("[^\\p{ASCII}]", "");
    
  3. このASCII正規化列でテキスト検索を実行しますが、元のUnicode列のデータを表示します。

36
laalto

Android sqlite、LIKE and GLOBでは_COLLATE LOCALIZED_と_COLLATE UNICODE_の両方を無視します(これらは_ORDER BY_でのみ機能します) 。ただし、テーブルに列を追加しなくても解決策があります。@ asatが この回答 で説明しているように、GLOBを各文字をその手紙の利用可能なすべての選択肢Javaの場合:

_public static String addTildeOptions(String searchText) {
    return searchText.toLowerCase()
                     .replaceAll("[aáàäâã]", "\\[aáàäâã\\]")
                     .replaceAll("[eéèëê]", "\\[eéèëê\\]")
                     .replaceAll("[iíìî]", "\\[iíìî\\]")
                     .replaceAll("[oóòöôõ]", "\\[oóòöôõ\\]")
                     .replaceAll("[uúùüû]", "\\[uúùüû\\]")
                     .replace("*", "[*]")
                     .replace("?", "[?]");
}
_

そして(もちろん、文字通りこのようではありません):

_SELECT * from table WHERE lower(column) GLOB "*addTildeOptions(searchText)*"
_

このように、たとえばスペイン語では、ユーザーはmasまたはmásのいずれかを検索します-)は検索をm [aáàäâã] sに変換し、両方の結果を返します。

GLOBは_COLLATE NOCASE_を無視することに注意することが重要です。そのため、関数とクエリの両方ですべてを小文字に変換しました。 sqliteのlower()関数は非ASCII文字では機能しないことにも注意してください。ただし、これらはおそらくすでに置き換えているものです。

この関数は、GLOBワイルドカード_*_と_?_の両方を「エスケープされた」バージョンに置き換えます。

1
descatalogado

Android NDKを使用して、目的のICU(Unicodeの国際コンポーネント)を含むSQLiteソースを再コンパイルできます。ここでロシア語で説明されています: http: //habrahabr.ru/post/122408/

ICUを使用してソースを使用してSQLilteをコンパイルするプロセスは次のとおりです。

ICUでsqliteをコンパイルする方法は?

残念ながら、CPUごとに異なるAPKが作成されることになります。

0
BCS Software