【问题标题】:rails3 sqlite date comparison returning null setrails3 sqlite日期比较返回空集
【发布时间】:2012-07-13 20:17:59
【问题描述】:

我正在尝试选择 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) 可能存在环境问题,不知道该去哪里找。有什么想法可能导致这种情况吗?

【问题讨论】:

  • 这可能是 UTC 问题。当您通过 Ruby Record.all.map 加载时,记录日期已经转换为 UTC。但是在 where 子句中 Time.now 是当地时间。如果你使用 Time.now.iso8601 会得到什么?
  • 谢谢peterept,Time.now.iso8601 解决了这个问题!

标签: ruby-on-rails ruby sqlite datetime activerecord


【解决方案1】:

我的 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 in 语句(以在其间生成 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 实现错误(请参阅:https://bugs.freedesktop.org/show_bug.cgi?id=50575)。

我觉得这可能不是你的问题(因为 iso8601 解决了它),但希望这可以避免其他人的一些挫败感!

【讨论】:

    【解决方案2】:

    问题源于 SQLite 将日期时间值存储为字符串这一事实。因此,您必须完全匹配格式,同时考虑到字典排序顺序。对于 mySQL、Oracle、Postgres 等,列具有不同的数据类型,这绝不是问题。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-10
      • 1970-01-01
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多