1

クエリにはさまざまなバリエーションがあります。すべての値の型は文字列です! (理由は聞かないでください...) 最初のものは次のようになります。

SELECT * FROM item WHERE arg1=false

引数の文字列 ("sqlWhere") は次のようになります: "arg1=?"

インデックス 0 の arg(s)-Array (args) の文字列は次のようになります: "false"

これはうまくいきます。715 件の結果が得られました。

今、私がこのようなものを持っている場合:

SELECT * FROM item WHERE (arg1=40 OR arg2=42) AND arg3=false

これには 110 の結果が期待されます。しかし、結果はなく、例外はスローされません

Firefox SQLite Manager で生のクエリを生成する場合:

SELECT COUNT(*) FROM item WHERE (arg1=40 OR arg2=42) AND arg3=false

次のようなクエリを生成すると、「no such column: false」というエラーが表示されます。

SELECT COUNT(*) FROM item WHERE (arg1=40 OR arg2=42) AND arg3="false"

失敗しません。しかし。私はselectionargsを使用しています。私は、彼らがこの状況を避けるべきであることを読みました。しかし、そうではありません。でも、arg3 = "\"+"false"+"\"" または arg3 = "\'+"false"+"\'" または arg3="'"+"false"+ の selectionargs に入れた場合でも「」 うまくいきません。多分アンドロイド特有の問題?値「false」は、値のリストから取得されます。空文字列で初期化されます。

クエリ メソッドは次のようになります。

public List<Map<String,String>> getSearchResults(String sqlWhere, String[]args)
    {
        List<Map<String,String>> specs = new ArrayList<Map<String,String>>();
        String[] specnames = this.getSpecNames();

        Cursor cursor = mDb.query(dbSchema.SpecSchema.TABLE_NAME, specnames, sqlWhere, args, null, null, dbSchema.SpecSchema._ID + dbSchema.SORT_ASC);
        cursor.moveToFirst();
        while(!cursor.isAfterLast())
        {
            Map<String, String> temp = new HashMap<String, String>();
            for(int i = 0; i < specnames.length; i++)
                temp.put(specnames[i], cursor.getString(cursor.getColumnIndex(specnames[i])));
            specs.add(temp);

            cursor.moveToNext();
        }

        if(cursor != null)
            cursor.close();

        return specs;
    }
4

3 に答える 3

3

代わりのSQLiteDatabase方法を使用してください。

SELECT * FROM item WHERE (arg1=40 OR arg2=42) AND arg3=false

する必要があります

SQLiteDatabase db;
String table = "item";
String projection = null;
String selection = "(arg1=? OR arg2=?) AND arg3=?";
String[] selectionArgs = new String[] { "40", "42", "false" };
String sortOrder = null;

db.query(item, projection, selection, selectionArgs, sortOrder);

それほど簡潔ではありませんが、SQLインジェクションから保護し、問題(SQL構文エラーなど)を引き起こす可能性が低いという点で、はるかに安全です。

于 2012-07-27T13:51:58.690 に答える
1

のドキュメントにSQLiteDatabase.query()は次のように書かれています:

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

このクエリを実行すると:

SELECT * FROM item WHERE (arg1=40 OR arg2=42) AND arg3=false

-パラメーターを使用して引数をバインドするselectionArgsと、整数とブール値が文字列としてバインドされます。これはデータベースと同じではありません。すべての列がタイプであると言ったことは知っていますが、 SQLiteドキュメントTEXTを読んでください:

列のタイプ アフィニティは、その列に格納されるデータの推奨されるタイプです。ここで重要な点は、タイプは必須ではなく推奨されるということです。任意の列には、任意のタイプのデータを格納できます。選択肢が与えられた一部の列は、あるストレージ クラスを別のストレージ クラスよりも使用することを好むだけです。

つまり、文字列テーブルに整数値を挿入すると、SQLite はそれらを変換して整数として格納します。次の重要なポイントは比較です。

SQLite は 、比較を実行する前に、ストレージ クラス INTEGER、REAL、および/または TEXTの間で値を変換しようとする場合があります。[...]

  • 列値への単純な参照である式は、列と同じ親和性を持ちます。

ドキュメントでは、次の例を示しています。

CREATE TABLE t1(
    a TEXT,      -- text affinity
    b NUMERIC,   -- numeric affinity
    c BLOB,      -- no affinity
    d            -- no affinity
);

-- Because column "a" has text affinity, numeric values on the
-- right-hand side of the comparisons are converted to text before
-- the comparison occurs.
SELECT a < 40,   a < 60,   a < 600 FROM t1;
0|1|1

あなたの場合、それは次のことを意味します:

  1. -tableTEXTには整数が挿入され、それがINTEGERs として変換 (および格納) されます。
  2. 比較を実行するときは、TEXT値 (整数) を指定します。TEXTテーブルはその値が type であることを示しているため、それらは -values に変換する必要があります (ただし、そうする必要はありません) TEXT
  3. と比較INTEGERしますがTEXT、これは等しくないため、正しい結果が得られません。

異なるデータ型 (文字列以外) を SQLiteDatabase に挿入するには、Prepared Statementsを使用します。

于 2012-07-27T13:38:39.207 に答える
0

arg1 は列名で、変数名ではありません。したがって、最初のクエリを実行すると、arg1=false という名前の列を含むすべての行が検索されます。後続のすべてのクエリで、列 arg2 を追加してから列 arg3 を追加します。列 arg2 と arg3 はありますか? テーブルの作成に使用したコードを投稿できますか?

于 2012-07-27T13:05:26.540 に答える