SQLite 中的日期不起作用

Posted

技术标签:

【中文标题】SQLite 中的日期不起作用【英文标题】:Date in SQLite not working 【发布时间】:2018-12-13 08:59:27 【问题描述】:

为什么当我执行我的代码时它会返回表格的所有日期

代码

    Strign raw[] = "id","date"
    String args[] ="2017-6-24" 
    Cursor cursor = database.query("database1", raw , date + "<=?"
                        , args, null, null, null);

我尝试过但没有奏效的方法:

1) 我尝试在我的代码中输入“日期(示例日期)”

    Strign raw[] = "id","date"
    String args[] ="date(2017-6-24)" 
    Cursor cursor = database.query("database1", raw , "date("+date + ")<=?"
                        , args, null, null, null);

2)

    Strign raw[] = "id","date"
    String args[] ="2017-6-24" 
    Cursor cursor = database.rawQuery("SELECT * FROM database1 "+ 
                                       "WHERE date<="+"2017-6-24",null);

编辑

在我的应用程序中,我需要返回特定日期之前的所有日期,即如果我的日期表中有此日期

     | ID |   DATE   |
     -----------------
     |  1 | 2018-6-21|
     |  2 | 2015-5-12|
     |  3 | 2013-3-17|
     |  4 | 2017-2-13|

我在我的应用程序中输入日期'2017-6-24' 我需要返回之前的所有日期,即我需要获取

     | ID |   DATE   |
     -----------------
     |  2 | 2015-5-12|
     |  3 | 2013-3-17|
     |  4 | 2017-2-13|

但是当我尝试这样做时,我会得到表格的所有日期

【问题讨论】:

a/ 请将random date 替换为未能给出预期b/ 的实际示例,您的日期首先如何存储在数据库中?您确定它看起来与您在问题中包含的内容完全一样吗? c/您似乎出于某种原因使用的变量date 的值是多少?显然它应该有date 列的名称,但可能没有? 【参考方案1】:

当您使用原始版本时,您实际上是在发出查询:-

SELECT * FROM database1 WHERE date(date)<='random date';

即它将返回日期(例如字符串2018-01-01)小于或等于字符串随机日期的所有行。因此,由于 r 大于 2(或任何数字作为字符),因此它将返回所有行。

更具体地说:-

random 不是返回随机数的函数,随机日期也不是

尝试 1 将有效地发出查询:-

SELECT id,date FROM database1 WHERE date(date)<='date(random date)';

即如上所述,但第一个字符将是 d

尝试 2 将有效地发出查询:-

SELECT * FROM database1 WHERE date<=random date;

会因语法错误而失败,例如 near "date": syntax error

更具体地说:-

random 不是返回随机数的函数,随机日期也不返回随机日期。 random() 是 SQLite 的核心函数之一,可用于返回随机的 64 位有符号整数。

通过rawQuery 的第二个参数或query 的第四个参数传递的任何参数都将导致值被包含为字符串,因此SQLite 函数不能作为参数传递,因为它们将被视为一个字符串。

看起来你想要一些基于:-

的东西
SELECT * FROM database1 WHERE date<=date(random());
注意 上面假设使用String 而不是String 作为raw 变量的类型。

不是说上面的方法会起作用。长话短说(即必须使用 datetime() 并使用 'uniepoch' 来使用整数和一些其他操作),这将导致从 1970 年到远远超过甚至今天出生的人。您可能希望在相对较短的定义时间段内获得一个日期来返回任何行。

假设您想要基于当前日期一年内的日期的随机行集,那么您可以:-

SELECT * FROM database1 WHERE  date <= date('now','+'||(ABS(random())%365)||' DAYS');

这是做什么的:-

生成一个范围很大的随机数,有负值和正值,然后 使用ABS(n) 函数返回一个正值。 将该数字除以 365(相当于 1 年的天数)后返回模数(余数)。 将该天数添加到当前日期以得出一年内的日期作为 WHERE 子句的正确参数。

这可以使用:-

String raw[] = "id","date"
Cursor cursor = database.query("database1", raw , date <= date('now','+'||(ABS(random())%365)||' DAYS')
                    , null, null, null, null);
注意,这不一定是您想要的,您实际上并没有明确您的要求。相反,它是一个示例,说明如何获得可能合适或不合适的随机日期(例如,您可能想要一年前的日期,在这种情况下 + 可以改为-)。

编辑 1

回复:-

注意:当我说“随机日期”时,我指的是我放入的任何日期 括号不是函数'random()',例如我把 8-6-2018 “随机日期”在哪里,即日期

日期不应采用该格式,日期应采用(使用最可能合适的格式)yyyy-mm-dd,例如2018-06-08(同样应该这样存储在数据库中),

SQLite 预计日期的格式数量有限

SQL As Understood By SQLite - Date And Time Functions -Time Strings

使用 SELECT * FROM database1 WHERE date &lt;=(8-6-2018); 实际上是在说 SELECT * FROM database WHERE date &lt;= -2016(即 2018 年减 8 减 6,相当于 2018 年减 2)。

您将遇到许多问题,即您没有更改为可识别的格式。并不是说不可能,而是使用 8-6-2018(以及格式的排列,即 8-6-2018(8 个字符)、10-6-2018 现在是 9 个字符和 10-10-2018(10 个字符))需要转换为可用格式的复杂性。

例如你必须使用类似的东西:-

WITH 

 selection_date(sdate) AS ( SELECT '8-6-2018'), --<<<<<<<< selection value

 converted_selection_date(sdate,converted_selection) AS (
        SELECT DISTINCT
            sdate,
            CASE
            WHEN length(sdate) = 8 THEN
                substr(sdate,5,4)||'-0'||substr(sdate,3,1)||'-0'||substr(sdate,1,1)
            WHEN (length(sdate) = 9 AND substr(sdate,2,1) = '-') THEN -- d-mm-yyyy
                substr(sdate,6,4)||'-'||substr(sdate,3,2)|'-0'||substr(sdate,1,1)
            WHEN (length(sdate) = 9 AND substr(sdate,3,1) = '-') THEN -- dd-m-yyyy
                substr(sdate,6,4)||'-0'||substr(sdate,4,1)||'-'||substr(sdate,1,2)
            WHEN (length(sdate) = 10 AND substr(sdate,3,1) = '-') THEN -- dd-mm-yyyy
                substr(sdate,7,4)||'-'||substr(sdate,4,2)||'-'||substr(sdate,1,2)
            ELSE sdate||'----'||length(sdate)
        END AS converted_selection
        FROM selection_date
    ),

 converted_date_column(rid,converted_date) AS (
    SELECT rowid AS rid, 
        CASE 
            WHEN (length(date) = 8 AND substr(date,2,1) = '-') THEN -- d-m-yyyy 
                substr(date,5,4)||'-0'||substr(date,3,1)||'-0'||substr(date,1,1)
            WHEN (length(date) = 9 AND substr(date,2,1) = '-') THEN -- d-mm-yyyy
                substr(date,6,4)||'-'||substr(date,3,2)|'-0'||substr(date,1,1)
            WHEN (length(date) = 9 AND substr(date,3,1) = '-') THEN -- dd-m-yyyy
                substr(date,6,4)||'-0'||substr(date,4,1)||'-'||substr(date,1,2)
            WHEN (length(date) = 10 AND substr(date,3,1) = '-') THEN -- dd-mm-yyyy
                substr(date,7,4)||'-'||substr(date,4,2)||'-'||substr(date,1,2)
            ELSE date
            END AS converted_date
    FROM argent
    )
    SELECT date FROM argent, converted_selection_date WHERE date <= converted_selection
;

编辑 2

回复:-

最简单的解决方案是始终使用 10 字符格式,即 yyyy-mm-dd,而不是 8-10 字符格式,例如

使用 2017-06-242017-06 而不是 2017-6-242017-6-1 -01。 (即在小于 10 的月份和天数中以 0 开头)

在这种情况下,原始和 2) 将照原样工作。

1) 工作可能是:-

String raw[] = "id","date"
String args[] ="random date" 
Cursor cursor = database.query("database1", raw , "date(date)<=date(?)"
                    , args, null, null, null);

即只有值本身是参数,where 子句的其余部分是硬编码的,因此不会被引用。

虽然比上面的转换示例简单,但如果格式保持为8-10,那么你仍然需要像上面那样进行一些转换,以免得到不需要的结果。

例如如果选择日期是 2017-2-1,那么 2017-10-1 会出现使用原始和 2)(1 根本无法正常工作)的情况。因为字符串 2017-1.... 小于字符串 2017-2....

【讨论】:

当我说“随机日期”时,我指的是我放在括号内的任何日期,而不是函数'random()',例如,我把 8-6-2018 放在哪里是“随机date" 即 date 您应该编辑您的问题以澄清。与其提供不同且模棱两可的代码,不如提供您正在使用的实际代码。您还应该给出一个随机日期或随机日期的示例,以及它是如何在您的编码器中传递的。还要显示日期如何存储在日期列中。 很抱歉让您浪费时间。我编辑了我的问题以使其更清楚 学习曲线的所有部分都没有问题,将尝试在适当的时候提出解决方案。当您更改为可用格式时,它应该很容易。如果月份总是 2 个字符会简单得多(我假设这个) 非常感谢你,现在我得到了我想要的日期。如果我第一次提问就让你浪费了时间,我真的很抱歉。

以上是关于SQLite 中的日期不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在具有多个表的 sqlite 数据库中删除行不起作用

从SQlite引入数据时,微调器选择不起作用

父 - 事务下 PHP PDO SQLite 中的子表 - 没有错误,但它不起作用

System.Data.Sqlite 1.0.99 引导比较不起作用

SQLite 自动增量不起作用

SQLite 删除特定行不起作用