Python SQLite,在sql查询中传递日期值

时间:2014-08-13 23:42:47

标签: python sql sqlite

我在将日期值插入SQL查询时遇到问题。我正在使用sqlite3和python。查询是:

c.execute("""SELECT tweeterHash.* FROM tweeterHash, tweetDates WHERE
        Date(tweetDates.start) > Date(?) AND
        Date(tweetDates.end) > Date(?)""",
          (start,end,))

查询不返回任何值,并且没有错误消息。如果我使用此查询:

c.execute("""SELECT tweeterHash.* FROM tweeterHash, tweetDates WHERE
        Date(tweetDates.start) > Date(2014-01-01) AND
        Date(tweetDates.end) > Date(2015-01-01)""")

然后我得到了我想要的值,这是预期的吗?

值start和end来自文本文件:

f = open('dates.txt','r')
start = f.readline().strip('\n')
end = f.readline().strip('\n')

但我也尝试过宣布它:

start = '2014-01-01'
end = '2015-01-01'

我想我不明白为什么从开头和结尾变量传入字符串并不起作用?将日期变量传递给SQL查询的最佳方法是什么?任何帮助是极大的赞赏。

1 个答案:

答案 0 :(得分:2)

这些日期并不相同 - 而且是您错误的非参数化日期。

Date(2014-01-01)计算算术表达式2014 - 01 - 01,然后从结果数Date构造2012,这将在公元前4707年为您提供一些东西。

Date('2014-01-01')Date(?),其中参数为字符串'2014-01-01',构建了2014年AD所需的日期。

只需直接选择日期即可更轻松地看到这一点:

>>> cur.execute('SELECT Date(2014-01-01), Date(?)', ['2014-01-01'])
>>> print(cur.fetchone())
('-4707-05-28', '2014-01-01')

同时

  

将日期变量传递给SQL查询的最佳方法是什么?

理想情况下,使用实际日期对象而不是字符串。 sqlite3库知道如何处理datetime.datetimedatetime.date。并且不要在值上调用Date,只需比较它们即可。 (是的,sqlite3可能会将它们比作字符串而不是日期,但是使用类似ISO8601的格式的全部意义在于它总是会给出相同的结果......除非你有一堆公元前4707年左右的日期。)所以:

start = datetime.date(2014, 1, 1)
end = datetime.date(2015, 1, 1)
c.execute("""SELECT tweeterHash.* FROM tweeterHash, tweetDates WHERE
        tweetDates.start > ? AND
        tweetDates.end > ?""",
          (start,end,))

  

这也意味着当我创建表格时,我想要:“开始日期时间,结束日期时间”,?

那会有用,但我不会这样做。 Python会将date个对象转换为ISO8601格式的字符串,但不会转换回SELECT,SQLite会让您透明地将这些字符串与Date函数返回的值进行比较。

您可以使用TEXT获得相同的效果,但我相信您会发现它不那么令人困惑,DATETIME会将列关联设置为NUMERIC,这可能会混淆人类和当你实际存储字符串时的其他工具。

或者您可以使用类型DATE - 这对SQLite和DATETIME一样没有意义,但它可以告诉Python透明地将返回值转换为datetime.date个对象。请参阅sqlite3文档中的Default adapters and converters

此外,如果您还没有阅读Datatypes in SQLite Version 3SQLite and Python types,那么您真的应该这样做;有很多东西都令人惊讶(甚至 - 或者尤其是 - 如果你使用过其他数据库),并且可能非常有用。


与此同时,如果您认为通过传递Date(2014-01-01)获得了“正确”的结果,那么这意味着您实际上已经在数据库中获得了大量垃圾值。并且没有办法解决它们,因为错误是不可逆的。 (毕竟,2014-01-01和2015-01-02都是2012 ...)希望您不需要旧数据,或者可以重新生成它。否则,您需要某种解决方法,以便在这种情况下尽可能有用地处理现有数据。