Android Sqlite选择args []值不正确?

时间:2012-07-27 12:25:39

标签: android sqlite

我有不同的查询变体。所有值类型都是字符串! (不要问为什么......) 第一个看起来像这样:

SELECT * FROM item WHERE arg1=false

arg(s)的字符串(“sqlWhere”)如下所示: “ARG1 =?”

索引0处的arg(s)-Array(args)的字符串如下所示: “假”

这很好用。我有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

我会收到错误:“没有这样的列:false” 如果我生成这样的查询:

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

它不会失败。但。我正在使用selectionargs。我读过,他们应该避免这种情况。但他们没有。甚至,如果我输入arg3 =“\”+“false”+“\”“或arg3 =”\'+“false”+“\'”或甚至arg3 =“'”+“false”+的选择标记“'”它不起作用。也许是一个Android特定的问题? 值“false”来自值列表。它使用emty字符串初始化。

Query-Method如下所示:

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;
    }

2 个答案:

答案 0 :(得分:3)

使用SQLiteDatabase方法intead。

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语法错误等)。

答案 1 :(得分:1)

SQLiteDatabase.query()的文档说:

  

selectionArgs - 您可以在选择中包含?,它将被来自selectionArgs的值替换,以便它们出现   在选择中。 这些值将绑定为字符串。

执行此查询时:

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

并使用selectionArgs - 参数绑定参数,整数和布尔值将绑定为字符串。这与您的数据库中的不同。我知道您说的所有列都是TEXT类型,但请阅读SQLite Documentation

  

列的类型亲和力是存储数据的推荐类型   在那一栏中。这里的重要思想是类型   推荐,不是必需的。任何列仍然可以存储任何类型的   数据。只是有些列,在给定选择的情况下,会更喜欢   使用一个存储类而不是另一个存储类。

这意味着,当您在字符串表中插入整数值时,SQLite将转换它们并将它们存储为整数。下一个重点是comparison

  

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. 您的TEXT - 表格会插入整数,然后将其转换(并存储)为INTEGER s。
  2. 执行比较时,您会输入TEXT - 值(这是您的整数)。那些应该(但不是必须)转换为TEXT - 值,因为您的表格表明它的值是TEXT类型。
  3. 您将INTEGERTEXT进行比较,这是不相等的,因此无法提供正确的结果。

  4. 要将不同的数据类型(除字符串之外)插入SQLiteDatabase,请使用Prepared Statements