使用 ContentProvider 进行复杂原始查询的优雅方式
Posted
技术标签:
【中文标题】使用 ContentProvider 进行复杂原始查询的优雅方式【英文标题】:Elegant way of doing complex raw queries using a ContentProvider 【发布时间】:2011-05-31 18:11:46 【问题描述】:我使用ContentProvider
与我的应用程序的数据库对话,但遇到了一些问题。
我有一个稍微复杂的查询。它看起来像这样:
String sql =
"select " +
" tblHistory._id _id, " +
" tblHistory.item item, " +
" tblHistory.updated_on updated_on, " +
" (select _id from tblList " +
"where tblList.item = tblHistory.item) list_id, " +
" 1 priority, " +
"from " +
" tblHistory " +
"where " +
" tblHistory.status <> 'STATE_DELETING' and " + selection + " " +
"union " +
"select " +
" tblSearch._id _id, " +
" tblSearch.item item, " +
" -1 updated_on, " +
" (select _id from tblList " +
"where tblList.item = tblSearch.product_name) list_id, " +
" 2 priority, " +
"from " +
" tblSearch " +
"where " +
" not exists (select * from tblHistory " +
"where tblHistory.item = tblSearch.product_name) " +
"order by " +
" priority, _id asc";
c = mDb.rawQuery(sql, null);
选择是:
String where = "tblHistory.user_id="
+ Integer.toString(intUserId)
+ " and tblHistory.item like '%"
+ strSearch + "%'";
我的问题是我的子查询。我有一个需要添加的约束,但没有很好的方法将该约束沿管道传递到该方法。我需要在子查询中使用正确的 user_id。
此时,我认为我有两个选择:
1) 从选择中解析出user_id
子字符串。
2) 使用selectionArgs
将"user_id = " + Integer.toString(intUserId)
传递给方法。
还有其他想法吗?
我应该注意,虽然我不想做任何 hack-ish,但我已将我的 ContentProvider
设为私有,因为它仅供我的应用程序使用;所以如果我必须这样做,我可以。
【问题讨论】:
见***.com/a/6548733/633187。这能回答你的问题吗? 帮自己一个忙,用"" + intUserId
代替Integer.toString(intUserId)
。 :p
Andrew,扩展 Alex 的评论(这有点离题,并没有解决您的实际问题):在 Java 中将整数转换为字符串的最有效方法是使用 Integer.toString,但是如果要将结果与字符串连接,则只需编写: String where = "tblHistory.user_id=" + intUserId + " and tblHistory.item like '%" + strSearch + "%'";
【参考方案1】:
在处理这样的复杂查询时,构建器类可以派上用场。 它避免了您必须将它们转换为字符串,希望这对您有所帮助。
public class SqlQueryBuilder
private static final String SELECT = "SELECT";
private static final String COMA = " , ";
private static final String WHERE = " where ";
private static final String EQUALS = " = ";
private static final String NOT_EQUALS = " != ";
private static final String FROM = " FROM ";
private final StringBuilder mStrBuilder = new StringBuilder();
public void init()
mStrBuilder.setLength(0);
public SqlQueryBuilder select(Object ...columns)
mStrBuilder.append(SELECT);
for(Object column:columns)
mStrBuilder.append(column);
mStrBuilder.append(COMA);
return this;
public SqlQueryBuilder where(Object conditionVar)
mStrBuilder.append(WHERE);
mStrBuilder.append(conditionVar);
return this;
public SqlQueryBuilder equalsVal(Object equalsVal)
mStrBuilder.append(EQUALS);
mStrBuilder.append(equalsVal);
return this;
public SqlQueryBuilder notEqualsVal(Object notEqualsVal)
mStrBuilder.append(NOT_EQUALS);
mStrBuilder.append(notEqualsVal);
return this;
public SqlQueryBuilder from(Object from)
mStrBuilder.append(FROM);
mStrBuilder.append(from);
return this;
public String build()
final String sqlQuery = mStrBuilder.toString();
init();
return sqlQuery;
用法如下
SqlQueryBuilder sqlQueryBuilder = new SqlQueryBuilder();
String innerQuery = sqlQueryBuilder.select("_id").from("tblList")
.where("tblList.item").equalsVal("tblHistory.item").build();
String query = sqlQueryBuilder.select("tblHistory._id _id",
"tblHistory.item", "tblHistory.updated_on updated_on",
innerQuery + " list_id", "1 priority").build();
【讨论】:
以上是关于使用 ContentProvider 进行复杂原始查询的优雅方式的主要内容,如果未能解决你的问题,请参考以下文章
ANDROID_MARS学习笔记_S01原始版_010_ContentProvider