如何在我的Android应用程序中加入两个SQLite表?

kak*_*a47 95 sqlite android

背景

我有一个Android项目,它有一个包含两个表的数据库:tbl_questiontbl_alternative.

要使用问题和替代方法填充视图,我使用游标.在我尝试加入这两个表之前,获取所需的数据没有问题.

    Tbl_question  
    -------------
    _id  
    question  
    categoryid  
    Tbl_alternative
    ---------------
    _id 
    questionid 
    categoryid 
    alternative

我想要以下内容:

SELECT tbl_question.question, tbl_alternative.alternative where 
categoryid=tbl_alternative.categoryid AND tbl_question._id = 
tbl_alternative.questionid.` 
Run Code Online (Sandbox Code Playgroud)

这是我的尝试:

public Cursor getAlternative(long categoryid) {
            String[] columns = new String[] { KEY_Q_ID, KEY_IMAGE, KEY_QUESTION, KEY_ALT, KEY_QID};
             String whereClause = KEY_CATEGORYID + "=" + categoryid +" AND "+ KEY_Q_ID +"="+ KEY_QID;
             Cursor cursor = mDb.query(true, DBTABLE_QUESTION + " INNER JOIN "+ DBTABLE_ALTERNATIVE, columns, whereClause, null, null, null, null, null);
             if (cursor != null) {
                  cursor.moveToFirst();
             }
             return cursor;
Run Code Online (Sandbox Code Playgroud)

我发现这种形式比常规SQL更难形成查询,但是得到了使用这种方式的建议,因为它不易出错.

如何在我的应用程序中连接两个SQLite表?

paw*_*eba 200

你需要rawQuery方法.

例:

private final String MY_QUERY = "SELECT * FROM table_a a INNER JOIN table_b b ON a.id=b.other_id WHERE b.property_id=?";

db.rawQuery(MY_QUERY, new String[]{String.valueOf(propertyId)});
Run Code Online (Sandbox Code Playgroud)

使用 ?绑定而不是将值放入原始sql查询.

  • @necromancer,这个答案不值得投票.只需阅读stackoverflow中的[downvote的意思](http://stackoverflow.com/help/privileges/vote-down):`每当遇到一个令人震惊的,不费吹灰之力的帖子或答案时,请使用你的downvotes这显然也许是危险的错误. (29认同)

phr*_*eed 20

另一种方法是构造一个视图,然后像表一样查询.在许多使用视图的数据库管理器中,可以获得更好的性能.

CREATE VIEW xyz SELECT q.question, a.alternative  
   FROM tbl_question AS q, tbl_alternative AS a
  WHERE q.categoryid = a.categoryid 
    AND q._id = a.questionid;
Run Code Online (Sandbox Code Playgroud)

这是来自内存所以可能存在一些语法问题. http://www.sqlite.org/lang_createview.html

我提到这种方法,因为你可以在视图中使用SQLiteQueryBuilder,因为你暗示它是首选.

  • 对于像Oracle这样的RDBMS,视图可以为您带来一些性能提升,但根据我的经验,它们仅在性能或报告需要时才使用.或者换句话说,您不为您使用的每个连接查询创建视图.特别是在SQLite中,我不相信会有任何性能提升 - 根据这个问题的答案,SQLite使用子查询重写查询.stackoverflow.com/questions/25577407/performance-penalty-for-unused-view#25580319 Android的API可能会限制OP的工作,但`rawQuery()`是正确的答案. (4认同)

Arn*_*pta 13

除了@ pawelzieba的答案,这肯定是正确的,加入两个表,而你可以使用INNER JOIN这样的

SELECT * FROM expense INNER JOIN refuel
ON exp_id = expense_id
WHERE refuel_id = 1
Run Code Online (Sandbox Code Playgroud)

通过像这样的原始查询 -

String rawQuery = "SELECT * FROM " + RefuelTable.TABLE_NAME + " INNER JOIN " + ExpenseTable.TABLE_NAME
        + " ON " + RefuelTable.EXP_ID + " = " + ExpenseTable.ID
        + " WHERE " + RefuelTable.ID + " = " +  id;
Cursor c = db.rawQuery(
        rawQuery,
        null
);
Run Code Online (Sandbox Code Playgroud)

由于SQLite向后兼容支持原始查询方式,我们将该命令转换为 -

SELECT *
FROM expense, refuel
WHERE exp_id = expense_id AND refuel_id = 1
Run Code Online (Sandbox Code Playgroud)

因此能够采用SQLiteDatabase.query()辅助方法的优点

Cursor c = db.query(
        RefuelTable.TABLE_NAME + " , " + ExpenseTable.TABLE_NAME,
        Utils.concat(RefuelTable.PROJECTION, ExpenseTable.PROJECTION),
        RefuelTable.EXP_ID + " = " + ExpenseTable.ID + " AND " + RefuelTable.ID + " = " +  id,
        null,
        null,
        null,
        null
);
Run Code Online (Sandbox Code Playgroud)

有关详细的博客文章,请查看此 http://blog.championswimmer.in/2015/12/doing-a-table-join-in-android-without-using-rawquery


Mik*_*ll' 8

"不明确的列"通常表示相同的列名称出现在至少两个表中; 数据库引擎无法分辨出你想要的那个.使用全表名称或表别名来消除歧义.

这是我在编辑器中碰巧遇到的一个例子.这是来自别人的问题,但无论如何都应该有意义.

select P.* 
from product_has_image P
inner join highest_priority_images H 
        on (H.id_product = P.id_product and H.priority = p.priority)
Run Code Online (Sandbox Code Playgroud)