【问题标题】:SQLite query using CursorLoader使用 CursorLoader 的 SQLite 查询
【发布时间】:2014-08-11 15:08:15
【问题描述】:

我正在尝试在我的加载器中获取唯一的列值。我的代码是这样的:-

public Loader onCreateLoader(int id, Bundle args) {

    if (mSelectedSpinnerOption == 1) {
        return new CursorLoader(this, Suggestion.CONTENT_URI, Suggestion.PROJECTION,
                BadBehaviourColumns.PACKAGENAME="DISTINCT", null, BadBehaviourColumns.TIMESTAMP + " ASC ");
    } 

}

我想要所有具有不同包名称值的值。如何使用上面的代码实现这一点?

【问题讨论】:

    标签: android sqlite


    【解决方案1】:

    我写这个答案是因为我在使用 CursorLoader 查询时遇到了完全相同的问题,而我得到的只是与 database.query() 相关的答案。

    有一个简单的技巧可以用于 SQL 注入。这里没有使用 DISTINCT,而是使用了 GROUP BY,除非您的内存不足(参考:Huge performance difference when using group by vs distinct),否则它的工作速度更快。

    以下是您必须执行的查询以从 table_name 中获取不同的 column1 项。

    SELECT column1 FROM table_name GROUP BY column1;
    

    使用这种技术,您最终会执行查询。

    SELECT column1 FROM table_name where (column1 NOT NULL) GROUP BY (column1);
    

    以下是android中的实现。

    String selection = "(" + column1 + " NOT NULL) GROUP BY (" + column1 + ")";
    CursorLoader c =  new CursorLoader(this, uri, projection,
                selection, null, null);
    

    【讨论】:

      【解决方案2】:

      我自己破解了这个,是的,它非常类似于 SQL 注入。但是,只要您设法使生成的(生成的)SQL 最终正确,它就可以工作。看看这个例子:

      Cursor c_buckets = getContext().getContentResolver().query(baseUri,
           new String[]{PhotoContract.ThumbEntry.COLUMN_BUCKET_NAME,
                        PhotoContract.ThumbEntry.COLUMN_BUCKET_ID + " as _ID"},
            "1=1) GROUP BY " + PhotoContract.ThumbEntry.COLUMN_BUCKET_NAME
                 + ", " + PhotoContract.ThumbEntry.COLUMN_BUCKET_ID
                + ", ABS(0",
                  null,
                  PhotoContract.ThumbEntry.COLUMN_BUCKET_ID
           );
      

      query 调用中的selection 字段相当于结果查询的WHERE 子句。 “诀窍”是在selection 末尾的WHERE 子句之后添加GROUP BY 子句。 WHERE 子句用括号括起来,所以诀窍是在WHERE 子句(这里只是1=1)之后添加一个右括号,方法是将1=1) 添加到selection。然后你可以插入你的GROUP BY 子句。然而,由于 Android 会期望所有这些都是选择,所以它会在最后添加一个右括号!为了克服这个问题,您需要在末尾添加一些需要右括号的内容。我发现简单地将ABS(0 添加到分组中很方便。这对分组没有影响,它解决了语法问题,导致有效的SQL:

      SELECT images.bucket_display_name, images.bucket_id as _ID FROM images WHERE (1=1) GROUP BY images.bucket_display_name, images.bucket_id, ABS(0) ORDER BY images.bucket_id
      

      请注意,我正在使用别名添加所需的“_id”列,而不会干扰分组。

      Android Q (API 29) 更新: 为了在 API 29 (Android Q) 上工作,列名不能再以表名作为前缀。如,images.bucket_display_name 应该只是 bucket_display_name

      【讨论】:

      • 无法使这个 hack 工作。它总是添加一个不需要的括号。也许在以前的版本中它可以工作......
      • 你能发布生成的 SQL 吗?
      【解决方案3】:

      我自己找到了答案:-

      完整的查询是这样的——Select * from table_name where column_name1 in (select distinct column_name1 from table_name) group by column_name1。

      因此,使用上述查询中 where 之后的部分代替所问问题中的 Selection 将给出所有不同的列名称。

      【讨论】:

      • 这个答案是不正确的,它不会给出不同的列名,相反你会有错误说:SQLiteException: near GROUP
      猜你喜欢
      • 2012-04-12
      • 2011-11-26
      • 1970-01-01
      • 2012-06-19
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      • 2015-02-24
      • 1970-01-01
      相关资源
      最近更新 更多