SQLiteDatabase.rawQuery使用预准备语句不返回正确的结果

时间:2011-01-05 23:00:46

标签: java sql android sqlite prepared-statement

我准备好的SQL语句有一个奇怪且无法解释的错误,它没有提供与noprepared语句相同的结果。

这两个版本不应该返回相同的结果吗?

准备版本(结果错误):

sb.append(" WHERE c.deck_id=? AND c.next_date < ? AND c.next_date > 0 AND c.active > 0 AND c.deck_level=?");
...
return db.rawQuery(sb.toString(), new String[] { Long.toString(deckId)
, Long.toString(now), Long.toString(level)});

非准备版本(按预期正常工作并获得正确结果):

sb.append(" WHERE c.deck_id=").append(deckId)
.append(" AND c.next_date<").append(now)
.append(" AND c.next_date > 0 AND c.active > 0 AND c.deck_level=").append(level);
...
return db.rawQuery(sb.toString(), null);

预分段语句版本中的错误在哪里?

更新的 我为这两个版本制作了额外的日志。

Log.d(TAG, "selectionArgs1:" + Long.toString(deckId) + ""+Long.toString(now)+ ""+Long.toString(level)+ "");
输出:selectionArgs1:* 5 * 1294429481330 * 5 * (SO:在源中不显示*)

StringBuffer d = new StringBuffer("selectionArgs2:");
d.append(deckId).append("").append(now).append("").append(level).append("");
Log.d(TAG, d.toString());
输出:selectionArgs2:* 5 * 1294429481330 * 5 *

1 个答案:

答案 0 :(得分:1)

我怀疑它与type affinity有关,但我无法像你描述的那样重现完全这个问题。

亲和行为会影响比较表达,所以'无准备'

next_date < 12345678

可能不等同于'准备好':

next_date < '12345678'

注意'rawQuery'绑定应用的隐含字符串数据类型 - rawQuery* javadoc说:

  

值将绑定为字符串。

我尝试使用next_date INTEGER字段来制作测试用例但无济于事。但是,如果该字段是无类型的,如:

CREATE TABLE cards ( next_date );

INSERT INTO cards SELECT 1234;
INSERT INTO cards SELECT '1234';

SELECT 'int', typeof( next_date ), next_date FROM cards WHERE next_date < 1234;
SELECT 'str', typeof( next_date ), next_date FROM cards WHERE next_date < '1234';

然后可以看到不同的亲和行为 - 结果是:

str|integer|1234

(也许这是一个评论,但更容易阅读格式化为答案。)

* http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#rawQuery(java.lang.String中,%20java.lang.String [])