SQLiteQueryBuilder中的selectionArgs不适用于列中的整数值

时间:2013-08-02 09:51:51

标签: android sql sqlite android-sqlite

我正在尝试从数据库中选择一些数据,我有两片代码来执行此操作:

cursor = builder.query(db,
                    new String[]{"col1", "col2", "col3"},
                    "id = ?", new String[]{getSID(db)}, null, null, null);

cursor = builder.query(db,
                    new String[]{"col1", "col2", "col3"},
                    "id = " + getSID(db), null, null, null, null);

它们之间的区别在于,根据文档,第一个似乎更正确,但它也不起作用 - 光标是空的。而不是第二个 - 我得到了我需要的所有数据。

所以我尝试在我的电脑上使用数据库副本执行不同的SQL查询,这就是我所拥有的:

SELECT col1, col2, col3 FROM SomeTables WHERE (id = '42')

这个不起作用(这个查询显然等于查询,由第一个代码示例生成)

SELECT col1, col2, col3 FROM SomeTables WHERE (id = 42)

这个工作正常(等于从第二个代码示例查询)。

据我所知,SQLite应该自动执行类型转换,但出了点问题,我不知道为什么。您对如何修复第一个代码示例有什么想法吗? (或者,也许,数据库?)

如果重要,请使用CREATE字段的表格的简化id脚本:

CREATE TABLE SomeTable ( ID PRIMARY KEY, col1, col2, [...] )

UPD:顺便说一句,getSID(db)返回String Object。

3 个答案:

答案 0 :(得分:8)

那个查询参数只能是字符串,这是Android数据库API中一个可怕的设计错误。

尽管文档说的是,但您应该仅将参数用于实际的字符串值;整数值可以安全地直接嵌入到SQL字符串中。 (对于blob,您必须使用接受ContentValues的函数。)

请注意,虽然SQLite使用dynamic typing,但在大多数情况下,不同类型的值比较相等(SELECT 42='42';返回0)。 在某些情况下,SQLite 会自动转换由type affinity引起的值(在您的情况下,如果您将id列声明为INTEGER,则会发生这种情况),但这是违反直觉的,所以不应该依赖它。

答案 1 :(得分:2)

根据SQLite documentation

  

SQLite版本3数据库中的任何列(INTEGER PRIMARY KEY列除外)都可用于存储任何存储类的值。

在我的情况下,这意味着我们无法确定哪些数据类型将存储在列中。如果您可以在数据类型放入数据库时​​控制和转换数据类型 - 在向数据库添加数据时可以将id值转换为TEXT并轻松使用selectionArgs。但这不是我的问题的答案,因为我必须按原样处理数据库内容。

所以,可能的解决方案:

a)在selection字符串中嵌入整数值,而不将它们包装到'中:

cursor = builder.query(db,
                    new String[]{"col1", "col2", "col3"},
                    "id = " + getSID(db), null, null, null, null);

b)来自selectionArgs的投射值:CAST(? as INTEGER)CAST(id AS TEXT)。我认为,将列转换为TEXT是更好的解决方案,因为右操作数总是TEXT,但左边的操作数可以是任何内容。所以:

cursor = builder.query(db,
                    new String[]{"col1", "col2", "col3"},
                    "CAST(id AS TEXT) = ?", 
                    new String[]{getSID(db)}, null, null, null);

答案 2 :(得分:1)

在传递给查询之前,您需要将 int id转换为string,因为参数数组的类型为字符串。例如:

cursor = builder.query(db, new String[]{"col1", "col2", "col3"},
    "id = ?", new String[]{String.valueOf(getSID(db))}, null, null, null);

它在第二类查询中工作的原因是因为您使用字符串附加整数值,该字符串会自动将int转换为String。例如:

int i = 10;
String s = i + "";   //now 10 is in string