Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 针对Heroku的Rails数据库特定查询_Mysql_Ruby On Rails_Database_Postgresql_Heroku - Fatal编程技术网

Mysql 针对Heroku的Rails数据库特定查询

Mysql 针对Heroku的Rails数据库特定查询,mysql,ruby-on-rails,database,postgresql,heroku,Mysql,Ruby On Rails,Database,Postgresql,Heroku,我最近在Heroku上部署了一些应用程序。我在本地开发机器上运行MySQL,花了一点时间更新我的一些作用域,以便在PostgreSQL中工作。然而,我收到的一个错误证明很难更改 目前,我的模型中有一个特定于数据库的case语句。我理解MySQL日期函数出现错误的原因,但我不确定这是否是最有效的解决方案。有没有人有更好的方法来实现一个可以同时使用MySQL和PostgreSQL的修复程序 case ActiveRecord::Base.connection.adapter_name whe

我最近在Heroku上部署了一些应用程序。我在本地开发机器上运行MySQL,花了一点时间更新我的一些作用域,以便在PostgreSQL中工作。然而,我收到的一个错误证明很难更改

目前,我的模型中有一个特定于数据库的case语句。我理解MySQL日期函数出现错误的原因,但我不确定这是否是最有效的解决方案。有没有人有更好的方法来实现一个可以同时使用MySQL和PostgreSQL的修复程序

  case ActiveRecord::Base.connection.adapter_name
  when 'PostgreSQL'
    named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (date_part('year', created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_month, lambda { |*args| {:conditions => ["published = ? AND (date_part('month', created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_day, lambda { |*args| {:conditions => ["published = ? AND (date_part('day', created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
  else
    named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (YEAR(created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_month, lambda { |*args| {:conditions => ["published = ? AND (MONTH(created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_day, lambda { |*args| {:conditions => ["published = ? AND (DAY(created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
  end
仅供参考,这是我收到的PostgreSQL错误:

PGError: ERROR: function month(timestamp without time zone) does not exist LINE 1: ...T * FROM "articles" WHERE (((published = 't' AND (MONTH(crea... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. : SELECT * FROM "articles" WHERE (((published = 't' AND (MONTH(created_at) = '11')) AND (published = 't' AND (YEAR(created_at) = '2010'))) AND ("articles"."published" = 't')) ORDER BY created_at DESC LIMIT 5 OFFSET 0

提前感谢任何人提供的任何意见。

不幸的是,这种情况经常发生,但您的想法大体正确

您的第一种攻击方法是查看MySQL和Postres中是否都存在函数,但是在这种情况下这是不可能的

我要提出的一个建议是,在这个解决方案中存在大量代码重复。考虑到条件声明是这里唯一的兼容问题,我将仅考虑条件的兼容性检查:

半伪代码示例:

named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (#{by_year_condition} = ?)", true, (args.first)], :order => "created_at DESC"} }


#...code...

def by_year_condition
  if postgres
     "date_part('year', created_at)"
  else
     "YEAR(created_at)"
end

另一个选项是为每个日期部分(日、月和年)创建计算列,并直接查询这些列。您可以使用模型代码或触发器使它们保持最新。您还可以在年、月和日列上对各种组合进行索引。众所周知,当您在where子句中使用函数时,数据库在正确使用索引方面非常糟糕,尤其是当该函数从列的中间拉出一部分数据时


有三个独立列的好处是,您的查询将不再依赖于任何供应商的SQL实现。

您应该使用标准提取函数:

named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (extract(year from created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }

两者都支持。

是的,代码重复才是真正激发我的问题的原因,这是我想尝试和避免的事情。你的建议当然很好,谢谢。