从SQLite3迁移到PostgreSQL问题(部署到Heroku)

时间:2012-05-25 14:35:22

标签: sql ruby-on-rails postgresql heroku

由于我的开发环境默认设置为sqllite3,因此我遇到了将rails代码部署到Heroku的一些问题。这是以下日志快照:

ActiveRecord::StatementInvalid (PG::Error: ERROR:  syntax error at or near ":"
2012-05-25T14:11:55+00:00 app[web.1]: 
2012-05-25T14:11:55+00:00 app[web.1]: LINE 1: ...LECT "records".* FROM "records"  WHERE (TIMESTAMP(:order) >=...
2012-05-25T14:11:55+00:00 app[web.1]: : SELECT "records".* FROM "records"  WHERE (TIMESTAMP(:order) >= '2011-05-25 00:00:00' and TIMESTAMP(:order) <= '2012-05-25 23:59:59') ORDER BY created_at):
2012-05-25T14:11:55+00:00 app[web.1]:   app/controllers/records_controller.rb:20:in `index'

我的控制器文件中的代码片段:

opts = {:order => "created_at"}
opts[:conditions] = (@start_date.nil? ? "" : "TIMESTAMP(created_at::text) >= '#{@start_date.to_s(:db)}'")
opts[:conditions] += ((@start_date.nil? || @end_date.nil?) ? "" : " and ")
opts[:conditions] += (@end_date.nil? ? "" : "TIMESTAMP(created_at::text) <= '#{@end_date.to_s(:db)}'")

最初,我有一个“DATETIME”,你有TIMESTAMP,所以我切换它仍然遇到问题。这段代码的上下文是我在日期之间运行查询,格式如下:2011-05-25 00:00:00

1 个答案:

答案 0 :(得分:1)

您的created_at应该已经timestamp,因此TIMESTAMP(created_at::text)无需尝试将其投放到timestamp;无论如何,timestamp(x)将无法在PostgreSQL中运行。你不应该为SQLite提供那种东西。

您最终会像这样运行SQL:

SELECT "records".*
FROM "records"
WHERE TIMESTAMP(:order) >= '2011-05-25 00:00:00'
  and TIMESTAMP(:order) <= '2012-05-25 23:59:59'
ORDER BY created_at

你正在做一些在SQL中将created_at::text更改为:order的地方。我无法重现这种行为,但我怀疑你正在与命名占位符(即column = :value而不是column = ?)发生冲突,但这只是一个疯狂的猜测。

在任何情况下,如果摆脱timestamp(...)内容并转而关联where来电,您将获得更好的内容:

query = Record.order(:created_at)
query = query.where('created_at >= ?', @start_date) if(@start_date.present?)
query = query.where('created_at <= ?', @end_date)   if(@end_date.present?)

然后您可以query.allquery.paginate(...)或其他任何方式获得最终结果。那就是(恕我直言)比一堆字符串争吵更漂亮,它应该在任何地方都一样。

如果您要在PostgreSQL(即Heroku)之上进行部署,那么您应该在PostgreSQL之上进行开发和测试。 SQLite对SQL是什么以及它的类型系统如何工作有一些奇怪的想法,PostgreSQL(幸运的是)更不宽容。您应始终在同一堆栈上进行开发和部署,相同一直应用到版本号。