如何使用内容提供程序在 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 < 'datetime(''now'')' AND transaction_date >= '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";
并通过null
与selectionArgs
联系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 会为事务中的第二个查询提供“数据库已锁定”?