2012-07-13 126 views
1

我试图选择SQLite数据库中的所有记录在日后有日期。rails3 sqlite日期比较返回空集

Record.where('scheduled_date > ?', Time.now) 

在我的电脑上,这当前返回一个空数组。

不过,如果我使用以下命令:

Record.all.map { |record| record if record.scheduled_date > Time.now } 

我收到的所有记录与将来的日期的数组。

此外,我的同事在他的机器上运行相同的Rails项目能够使用ActiveRecord查询成功返回预期的结果数组。在最近取消对项目的更改后,此查询未能为他工作,他的计算机的行为与我的相似。

我怀疑在这个Rails项目中SQLite(v.1.3.6)或Rails3(v.3.2.3)可能会造成环境灾难,并且不知道在哪里寻找。任何想法可能会造成这种情况?

+1

这可能是一个UTC问题。当您通过Ruby Record.all.map加载时,记录日期已经转换为UTC。但在Time.now的where子句中是当地时间。如果你使用Time.now.iso8601,你会得到什么? – peterept 2012-07-14 10:37:41

+0

谢谢peterept,Time.now.iso8601解决了这个问题! – 2012-07-16 15:07:15

回答

0

我和我的sqlite3开发数据库有类似的问题。

我们使用ActiveSupport :: TimeWithZone :: to_s(:db)为种子数据库(调用ActiveRecord :: connection.execute的速度 - 不要判断我为我的同事的代码:)。

sql =<<-EOL 
    INSERT INTO some_table(day) 
    VALUES('#{Time.zone.now.beginning_of_day.to_s(:db)}') 
EOL 
SomeTable.connection.execute(sql) 

对于查询,我将一个TimeWithZone范围传递给语句中的一个ARel(以在其间生成一个sql)。

SomeTable.where(SomeTable.arel_table[:day].in((Time.zone.now.beginning_of_day)..(1.day.from_now))) 

时间戳从to_s(:DB)看起来是这样的:2013-10-01 04:00:00

在AREL生成的查询中的时间戳看起来是这样的:2013-10-01 04:00:00.000000

即使这些应该是等价的,数据库解释后者比前者晚。我无意中偶然发现了小数秒的差异,它看起来像我的sqlite3实现bug(请参阅:https://bugs.freedesktop.org/show_bug.cgi?id=50575)。

我有一种感觉,这可能不是你的问题(因为iso8601解决了它),但希望这可以节省别人一些挫折!

0

问题源于SQLite将日期时间值存储为字符串的事实。因此,您必须完全匹配格式,并将字典排序顺序考虑在内。有了mySQL,Oracle,Postgres等,其中列有一个独特的数据类型,这从来都不是问题。

获得预期结果的另一种方法是执行“datetime(the_column)> =?”或者甚至是“datetime(the_column)> = datetime(?)”,尽管这当然效率要低得多。