为什么这个Sqlite日期比较有效?

时间:2018-03-15 16:03:05

标签: python datetime sqlite

当Sqlite列声明为timestamp时,我知道这有效:

import sqlite3, datetime
dbconn = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
c = dbconn.cursor()
c.execute('create table mytable(title text, t timestamp)')

c.execute('insert into mytable (title, t) values (?, ?)', ("hello", datetime.datetime(2018,3,10,12,12,00)))
c.execute('insert into mytable (title, t) values (?, ?)', ("hello2", datetime.datetime(2018,3,1,0,0,00)))

d1 = datetime.datetime(2018,3,10)
d2 = datetime.datetime(2018,3,11)

c.execute("select * from mytable where t >= ? and t < ?", (d1, d2))

for a in c.fetchall(): 
    print a

# Result: (u'hello', datetime.datetime(2018, 3, 10, 12, 12))

但是,当t列定义为TEXT时,为什么它仍然有效?根据{{​​3}},似乎日期时间将存储为字符串。然后为什么这样的>=<比较仍然有效?这是巧合还是良好做法?

import sqlite3, datetime
dbconn = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
c = dbconn.cursor()
c.execute('create table mytable(title text, t text)')  # <--- here t has TEXT type

c.execute('insert into mytable (title, t) values (?, ?)', ("hello", datetime.datetime(2018,3,10,12,12,00)))
c.execute('insert into mytable (title, t) values (?, ?)', ("hello2", datetime.datetime(2018,3,1,0,0,00)))

d1 = datetime.datetime(2018,3,10)
d2 = datetime.datetime(2018,3,11)

c.execute("select * from mytable where t >= ? and t < ?", (d1, d2))

for a in c.fetchall(): 
    print a

# Result: (u'hello', u'2018-03-10 12:12:00')

奇怪的是:如果日期时间只是作为字符串存储,那么为什么这样的时间间隔比较有用呢?比较字符串是否比较幸运(如何{{1} }和<?)在这里正确吗?

2 个答案:

答案 0 :(得分:1)

ISO 8601日期/时间格式YYYY-MM-DD HH:MM::SS专门用于允许与按时间顺序排序顺序相对应的词典排序。因此,这种格式的字符串之间的比较是有效的,因为这是它的工作方式。

根据SQLite docs,每当比较2个字符串时,使用适用的校对序列来比较2个字符串。使用的归类序列取决于以下规则:

  

7.1。从SQL

分配整理序列      

每个表的每一列都有一个关联的整理功能。如果未明确定义整理功能,则整理功能默认为BINARY。列定义的COLLATE子句用于为列定义备用整理函数。

     

确定用于二元比较运算符(=,&lt;,&gt;,&lt; =,&gt; =,!=,IS和IS NOT)的整理函数的规则如下:

     
      
  1. 如果任一操作数使用后缀COLLATE运算符进行显式整理功能分配,则显式整理功能用于比较,优先于左操作数的整理功能。

  2.   
  3. 如果任一操作数是一列,则使用该列的整理功能优先于左操作数。出于上一句的目的,以一个或多个一元“+”运算符开头的列名仍被视为列名。

  4.   
  5. 否则,BINARY整理功能用于比较。

  6.   

请注意,将日期/时间值存储为任何其他格式的字符串,这些格式不会按时间顺序按字典顺序进行比较,从而导致日期/时间比较通常是错误的。

答案 1 :(得分:0)

  

为什么当列t定义为TEXT时它仍然有效?看来,根据&gt;这个文档,日期时间将存储为字符串。那么为什么呢? a&gt; =,&lt;比较还有用吗?这是巧合还是好的做法?

无论列t是定义为TEXT还是TIMESTAMP,日期时间都存储为字符串。

  

在这里正确比较字符串(&lt;和&gt;?)是否真的很幸运?

是。在Python 2中,字符串按其字符的ASCII值从左到右进行比较。所以,如果你有两个字符串,&#34; 001&#34;和&#34; 010&#34;,python比较第一个字符:&#34; 0&#34;和&#34; 0&#34;,发现它们相等,然后比较下一个字符:&#34; 0&#34;和&#34; 1&#34;。因为&#34; 1&#34;具有比&#34; 0&#34;更大的ASCII值,字符串&#34; 010&#34;大于&#34; 001&#34;。

如果您担心不同的日期时间格式,可以使用sqlite的日期时间函数(https://www.sqlite.org/lang_datefunc.html)在它们之间进行转换。