以下任何内容都可以更改,以达到可行的解决方案! 我可以完全控制以下所有架构/数据/查询/代码,所以任何合理的欢迎改进:我正在寻找一个简单/清洁/到点的解决方案。例如,制作两个不同的查询(= ?
和is null
)是最后的手段。
我想更改以下代码,以便我可以致电listCategoriesIn(1)
和listCategoriesIn(null)
,他们都会给出正确的预期结果。
我无法listCategoriesIn(null)
使用WHERE
这样的c.parent = ?
条款。
INTEGER
或NULL
绑定到= ?
?WHERE
子句以使其适用于这两种情况?CREATE TABLE Category (
_id INTEGER NOT NULL,
name VARCHAR NOT NULL,
parent INTEGER NULL --< important bit
CONSTRAINT fk_Category_parent
REFERENCES Category(_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
PRIMARY KEY(_id AUTOINCREMENT),
UNIQUE(name)
);
INSERT INTO Category
(_id, parent, name)
SELECT 0, NULL, 'cat0' --< expected for listCategoriesIn(null)
UNION SELECT 1, NULL, 'cat1' --< expected for listCategoriesIn(null)
UNION SELECT 11, 1, 'cat1-1' --< expected for listCategoriesIn(1)
UNION SELECT 12, 1, 'cat1-2' --< expected for listCategoriesIn(1)
UNION SELECT 121, 12, 'cat1-2-1'
UNION SELECT 122, 12, 'cat1-2-2'
UNION SELECT 13, 1, 'cat1-3' --< expected for listCategoriesIn(1)
UNION SELECT 131, 13, 'cat1-3-1'
UNION SELECT 2, NULL, 'cat2' --< expected for listCategoriesIn(null)
UNION SELECT 21, 2, 'cat2-1'
UNION SELECT 3, NULL, 'cat3' --< expected for listCategoriesIn(null)
;
IRL我使用了更复杂的视频,子查询和多个JOIN。
select
c.*,
(select count() from Category where parent = c._id) as count
from Category c
where c.parent = ? --< important bit
;
public Cursor listCategoriesIn(SQLiteDatabase db, Long categoryID) {
// public Cursor SQLiteDatabse.rawQuery(String sql, String[] selectionArgs);
return db.rawQuery(CATEGORY_QUERY, new String[] {
String.valueOf(categoryID)
});
}
listCategoriesIn(1)
:工作正常
listCategoriesIn(null)
:生成的Cursor为空,可能绑定= 'null'
或= NULL
。
public Cursor listCategoriesIn(SQLiteDatabase db, Long categoryID) {
// public Cursor SQLiteDatabse.rawQuery(String sql, String[] selectionArgs);
return db.rawQuery(CATEGORY_QUERY, new String[] {
categoryID == null? null : categoryID.toString()
});
}
listCategoriesIn(1)
:工作正常
listCategoriesIn(null)
: java.lang.IllegalArgumentException:索引1处的绑定值为null
答案 0 :(得分:0)
我认为当字段为NULL时,您需要发送不同的SQL语句。
public Cursor listCategoriesIn(SQLiteDatabase db, Long categoryID) {
if(categoryID == null)
return db.rawQuery(CATEGORY_QUERY_NULL, null);
else
return db.rawQuery(CATEGORY_QUERY, new String[] { categoryID.toString() });
}
其中CATEGORY_QUERY_NULL与CATEGORY_QUERY相同,但使用c.parent IS NULL
代替c.parent = ?
。有关详细信息,请参阅此answer。
答案 1 :(得分:0)
在睡觉之后开始新的一天我有顿悟,可以不重复查询:
where c.parent = ? or (? = 'null' and c.parent is null)
但是我们需要复制参数,这里是相应的Java调用:
public Cursor listCategoriesIn(SQLiteDatabase db, Long categoryID) {
return db.rawQuery(CATEGORY_QUERY, new String[] {
String.valueOf(categoryID), String.valueOf(categoryID)
});
}
当categoryID
为null
时,没有NPE,因为它绑定为"null"
(请参阅valueOf
)。将null->'null'
传递给驱动程序会激活WHERE
子句的第二部分,当然INTEGER
个值中没有一个= 'null'
,所以第一部分不会播放。
这个技巧有效,因为rawQuery
binds everything as String
s和SQLite引擎可以处理INTEGER
与TEXT
中的数字进行比较。我确定可以在SQLite Datatypes documentation。