如何使用内容提供程序在 Sqlite 数据库中查询 Android 中的时间戳列?

Posted

技术标签:

【中文标题】如何使用内容提供程序在 Sqlite 数据库中查询 Android 中的时间戳列?【英文标题】:How to Query in Sqllite database for Timestamp Column in Android with Content provider? 【发布时间】:2021-10-22 23:25:45 【问题描述】:

我有一个带有时间戳列的数据库。 transaction table of my database 我想查询今天的日期,我为此编写了这样的 sql 查询

SELECT * from TransactionTable where transaction_date < datetime('now') 
AND transaction_date >= datetime('now','start of day') ORDER by transaction_date DESC

效果很好,但是当我将它包含在我的 Android 应用程序中时,它返回 0 行。 这是我在应用中添加的方式。

String selection =  myContractClass.myTransactionEntry.COLUMN_TRANSACTION_DATE + "  < ?" + " AND "
                + myContractClass.myTransactionEntry.COLUMN_TRANSACTION_DATE + " >= ?";
        String[] selectionArgs =  "datetime('now')" , "datetime('now','start of day')" ;
        try
        
            new FetchTransaction(selection,selectionArgs,"10").execute(myContractClass.myTransactionEntry.CONTENT_URI);
        catch (Exception e) 
            e.printStackTrace();
        
   
 

FetchTransaction 类的构造函数是这样的:

  public FetchTransaction(String selection,String[] args, String limit)
    
    this.selection = selection;
    this.selectionArgs = args;
    this.limit = limit;
    

并在 doInBackground 方法中执行此操作:-

  c = getContentResolver().query(
                    myContractClass.myTransactionEntry.CONTENT_URI.buildUpon()
                            .appendQueryParameter(myContentProvider.QUERY_PARAMETER_LIMIT,limit).build(),
                    projection, selection, selectionArgs, sortOrder);

为了进一步调查,我还提供了内容提供商的详细信息:-

    case TRANSACTION:

                SQLiteQueryBuilder sqLiteQueryBuilder = new SQLiteQueryBuilder();
                sqLiteQueryBuilder.setTables(myTransactionEntry.TABLE_NAME + " INNER JOIN " + myDbEntry.TABLE_NAME + " ON " +  myTransactionEntry.TABLE_NAME + "."
                        +myTransactionEntry.COLUMN_PRODUCT_ID + "=" +  myDbEntry.TABLE_NAME       + "." +myDbEntry._ID);
                //sqLiteQueryBuilder.setTables("TransactionTable  INNER JOIN Products ON TransactionTable.product_id_in_product_table = Products._ID");
                HashMap<String,String> columnprojection = new HashMap<String,String>();
               columnprojection.put(myTransactionEntry._ID , myTransactionEntry.TABLE_NAME + "." + myTransactionEntry._ID );
              columnprojection.put(myDbEntry.TABLE_NAME+ "." + myDbEntry.COLUMN_PRODUCT_NAME,  myDbEntry.TABLE_NAME       + "." +myDbEntry.COLUMN_PRODUCT_NAME + " AS " + "PNAME");
                columnprojection.put(myTransactionEntry.COLUMN_PRODUCT_QUANTITY_CHANGED,myTransactionEntry.TABLE_NAME + "." +myTransactionEntry.COLUMN_PRODUCT_QUANTITY_CHANGED + " AS " + "QTY");
                columnprojection.put(myTransactionEntry.COLUMN_TRANSACTION_TYPE,myTransactionEntry.TABLE_NAME + "." +myTransactionEntry.COLUMN_TRANSACTION_TYPE + " AS " + "TTYPE");
                columnprojection.put(myTransactionEntry.COLUMN_TRANSACTION_DATE,myTransactionEntry.TABLE_NAME + "." +myTransactionEntry.COLUMN_TRANSACTION_DATE + " AS " + "TDATE");
                columnprojection.put(myTransactionEntry.COLUMN_ANYREMARK,myTransactionEntry.TABLE_NAME + "." +myTransactionEntry.COLUMN_ANYREMARK+ " AS " + "TREMARK");
                columnprojection.put(myTransactionEntry.COLUMN_PRODUCT_ID, myTransactionEntry.TABLE_NAME + "." + myTransactionEntry.COLUMN_PRODUCT_ID + " AS " + "PID");
                sqLiteQueryBuilder.setProjectionMap(columnprojection);

            c = sqLiteQueryBuilder.query(db,null,
                    selection,selectionArgs,null ,null,sortOrder,limit);

问题出在哪里?为什么它返回 0 行而不是今天的数据。 我猜错误在 selectionArgs 但在 idk 中。

【问题讨论】:

链接到表的数据 (ibb.co/7gKyffD) 【参考方案1】:

您似乎将 SQLite 函数作为参数传递。因此,它们将被包含为文字(字符串),因此不会被识别为函数。

当参数被绑定时,你的 SQL 会产生类似的结果:-

SELECT * from TransactionTable where transaction_date &lt; 'datetime(''now'')' AND transaction_date &gt;= 'datetime(''now'',''start of day'')' ORDER by transaction_date DESC

不传递任何参数,因为没有任何参数,并将函数包含在选择字符串中。

所以你有:-

String selection =  myContractClass.myTransactionEntry.COLUMN_TRANSACTION_DATE + "  < datetime('now')" + " AND "
            + myContractClass.myTransactionEntry.COLUMN_TRANSACTION_DATE + " >= datetime('now','start of day')";

....

c = sqLiteQueryBuilder.query(db,null,selection,null,null ,null,sortOrder,limit);
注意以上为原理代码,未编译运行,可能存在错误。

【讨论】:

有时在寻找解决方案时,我们会深入研究并忘记基本的东西,感谢您的帮助【参考方案2】:

我想查询今天的日期

假设未来没有交易,则无需使用任何? 占位符并传递任何参数。

您所要做的就是使用函数DATE() 仅从时间戳中获取日期,并将其与返回当前日期的令牌CURRENT_DATE 进行比较:

String selection = "DATE(" + myContractClass.myTransactionEntry.COLUMN_TRANSACTION_DATE + ") = CURRENT_DATE";

或者,更简单:

String selection = myContractClass.myTransactionEntry.COLUMN_TRANSACTION_DATE + " >= CURRENT_DATE";

并通过nullselectionArgs 联系query()

c = sqLiteQueryBuilder.query(db, null, selection, null, null, null, sortOrder, limit);

【讨论】:

感谢@forpas,结合你的和 mikeT 我让它工作了。实际上,我不得不在选择字符串中使用日期时间函数而不是日期。 @Vivekgupta 如果您使用datetime(transaction_date),结果与transaction_date 完全相同,因为transaction_date 已经是一个时间戳(日期时间)。 我需要将其转换为 localtime ,否则结果是任意的。

以上是关于如何使用内容提供程序在 Sqlite 数据库中查询 Android 中的时间戳列?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用 Perl 的 DBD::SQLite 时,SQLite 会为事务中的第二个查询提供“数据库已锁定”?

Sqlite数据库中如何优化like查询

android上如何使用sqlite数据库

从我的内容提供商返回列的所有行

如何在sqlite数据库表中查询到含有换行的记录的全部信息,按照一般的方法只能查询到换行前的内容,后面无

如何在android中使用游标(sqlite查询)搜索数据库