1

この質問は、Android で SQLite が始まって以来、私を悩ませてきました。選択引数はStrings. 何?なんで?

私の問題を見てみましょう。データベースが適切に入力されました:

sqlite> select count (*) from issues where project_id = 1;
3819

偉大な。コードを見てみましょう。

public Cursor selectAllCursor(final long projectId) {
    final String selection = projectId > 0 ? KEY_PROJECT + " = ?" : null;
    final String[] selArgs = projectId > 0 ? new String[] {
        Long.toString(projectId)
    } : null;

    final Cursor c = mDb.query(TABLE_ISSUES, null, selection, selArgs, null, null, null);
    c.moveToFirst();
    return c;
}

さて、返されたCursorものは空です。なんで?

sqlite> select count (*) from issues where project_id = '1';
0

まあ、それが理由です。

私が見つけた唯一の修正は次のとおりです。

public Cursor selectAllCursor(final long projectId) {
    final String selection = projectId > 0 ? KEY_PROJECT + " = " + projectId : null;
    final String[] selArgs = null;

    final Cursor c = mDb.query(TABLE_ISSUES, null, selection, selArgs, null, null, null);
    c.moveToFirst();
    return c;
}

動作しますが、これは醜いと思います。選択引数がではなく の
配列ではないのはなぜですか? Android フレームワークはオブジェクト タイプをテストし、それが整数 ( / ) の場合は、これを整数として扱うように SQLite に指示します。ObjectStringintlong

4

2 に答える 2

1

パラメーターは、文字列の書式設定の問題 (SQL インジェクション攻撃を含む) を回避するのに役立ちます。他のタイプでは、このような問題はありません。

ただし、これは、値の型に応じて、まったく異なるコードを使用する必要があることを意味します。さらに、compileStatementを使用している場合は、他の型をパラメーターとして使用できますが、 SQLiteStatementは単一の値 (1 x 1) の結果セットに対してのみ機能します。

これは単なる悪い API 設計です。

テーブルの列を として宣言するとINTEGER、SQLite の型アフィニティ ルールによって値が自動的に数値に変換されます。ただし、これは のような直接比較でのみ機能しColumn = ?ます。

于 2013-02-18T17:02:20.497 に答える
0

そうです、ドキュメントは、パラメーターが常に文字列としてバインドされることを明確に示しています。それがなぜなのかはわかりません(それがあなたの実際の質問です:-))が、それを回避する方法が見つかりません。

selectionArgs ?s を選択に含めることができます。これは、selectionArgs からの値で置き換えられ、選択に表示されます。値は文字列としてバインドされます。

あなたが持っていることを行うための「より良い」方法は、おそらくString.formatを使用することですか? 例えば

String selection = String.format("%s = %d", KEY_PROJECT, projectId )
于 2013-02-18T16:30:13.317 に答える