【问题标题】:Can I perform this Android query with ContentResolver.query()? (LEFT JOIN and CASE)我可以使用 ContentResolver.query() 执行这个 Android 查询吗? (左连接和大小写)
【发布时间】:2011-09-14 09:24:58
【问题描述】:

我希望在 Android 上执行以下查询(以伪代码形式):

SELECT C.ID, C.NAME, CASE ISNULL(G.GROUPID,0) = 0 THEN 0 ELSE 1 END INGROUP
FROM CONTACTS C 
LEFT JOIN GROUPMEMBERSHIP G ON G.CONTACTID = C.ID AND G.GROUPID = ?

我希望通过默认的 Contacts ContentProvider 选择系统通讯录中所有联系人的 ID 和姓名,以及 0/1 字段指示联系人是否是组 ? 的成员。

我当然可以很容易地获取所有联系人,然后在我的 Adapter 类中很容易地循环并分别查询成员资格,但我想将这两个查询作为一个外部连接查询执行会产生更好的性能。

我可以使用标准的高级字符串投影和ContentResolver.query() 方法来做到这一点吗?还是这种查询需要深入挖掘更直接的 SQL 执行?

【问题讨论】:

    标签: android sql left-join android-contacts android-contentresolver


    【解决方案1】:

    编辑: 好的,所以这实际上并不能解决所提出的问题,因为 eidylon 与他们的问题中提到的现有 ContentProvider 相关联。但是,如果您拥有 ContentProvider 源和 API,这确实涵盖了如何执行 JOIN。所以我会把它留给那些想知道如何处理这种情况的人。


    这很简单!但是不直观... :)

    query(Uri uri, String[] projection, String selection, 
    String[] selectionArgs, String sortOrder)
    

    好的,那么 URI 是什么?通常,每个表都有一个 URI。

    content://com.example.coolapp.contacts 提供来自CONTACTS 表的数据。 content://com.example.coolapp.groupmembers 从您的 GROUPMEMBERSHIP 表中提供数据。

    但 URI 实际上只是一个字符串。随心所欲地使用它。在您的 ContentProvider 中创建一个响应 content://com.example.coolapp.contacts_in_group 的代码块。在 ContentProvider 中的该代码块中,您可以获得对 SQLite DB 的原始访问权限,而不受有限的 query() 数据模型的限制。随意使用!

    根据需要定义您的选择字段。他们没有映射到表列名——按照你需要的方式映射它们,以便获取你的参数。

    根据需要定义投影——它可能包含连接后两个表中的列。

    Bing,你完成了。谷歌在他们自己的代码中内部使用了同样的模型——去看看联系人提供者 API——你会看到“bla.RawContact”和“bla.Contact”等作为内容 URI。每个都从数据库中的同一张表中提供数据——不同的 URI 只是为同一张表提供不同的视图

    【讨论】:

    • 感谢您的回答...它非常详细且内容丰富,因此我投了赞成票;但显然 是我在我的 Q 中不清楚我正在查询 Android 联系人数据库,而不是我自己的数据库。你不是唯一一个错过这个的人。我已经更新了我的措辞,以便更清楚地说明这一点。谢谢! :)
    • 对不起,是的。如果您使用的是现有的contactProvider,那么您将无法使用它们实现的任何内容URI 和连接。
    • 所以总结一下,在您的 ContentProvider 中,覆盖“查询”方法,检查您的 URI,并通过直接连接到您的 SQLite 数据库来做任何您想做的事情?谢谢!
    • @jcwenger 你能给出在 contentResolver 上使用内部连接的示例代码吗?
    • @jcwenger 拜托,你觉得你能帮忙解决这个stackoverflow.com/questions/27257416/…吗?
    【解决方案2】:

    不,您不能使用ContentResolver.query() 方法进行此类查询。 你需要这样写:

    SQLiteDatabase db = YourActivity.getDbHelper().getReadableDatabase();
    String query = yourLongQuery;
    Cursor c = db.rawQuery(query, null);
    YourActivity.startManagingCursor(c);
    c.setNotificationUri(YourActivity.getContentResolver(), YourContentProvider.CONTENT_URI);
    

    【讨论】:

    • 通过四处搜索,我得到的印象是您不能使用 SQLLiteDatabase 查询其他应用程序......在我的例子中是 CONTACTS uri,但只能用于查询您自己的数据存储。它是否正确?在这种情况下,我想我在绑定我的活动时会被困在我的适配器类中执行子查询。
    • @eidylon:我不知道您正在查询联系人数据库。是的,你是对的:(
    • 该死!哦,好吧......向前和向上!谢谢!
    • 底线,必须是 THE 内容提供者并定义一个特殊的 URI,然后为复杂性构建特殊的查询。正确的? @ediyon - 我认为你可以接受 Macarse 的回答。
    【解决方案3】:

    你不能这样做,因为 ContentResolver 只有一种查询方法:

        query(Uri uri, String[] projection, String selection, 
    String[] selectionArgs, String sortOrder)
    

    表或 FROM 子句没有参数。

    【讨论】:

      猜你喜欢
      • 2021-08-22
      • 2013-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-29
      • 2010-12-24
      • 2015-02-06
      • 2019-06-17
      相关资源
      最近更新 更多