我有不同的查询变体。所有值类型都是字符串! (不要问为什么......) 第一个看起来像这样:
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;
}
答案 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)
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
在您的情况下,这意味着以下内容:
TEXT
- 表格会插入整数,然后将其转换(并存储)为INTEGER
s。TEXT
- 值(这是您的整数)。那些应该(但不是必须)转换为TEXT
- 值,因为您的表格表明它的值是TEXT
类型。INTEGER
与TEXT
进行比较,这是不相等的,因此无法提供正确的结果。要将不同的数据类型(除字符串之外)插入SQLiteDatabase,请使用Prepared Statements。