Ruby on rails Rails/Oracle:ActiveRecord find从控制台和应用程序返回不同的结果

Ruby on rails Rails/Oracle:ActiveRecord find从控制台和应用程序返回不同的结果,ruby-on-rails,oracle,activerecord,Ruby On Rails,Oracle,Activerecord,我最近开始将我的应用程序从使用sqlite移动到Oracle,并开始遇到以下问题: 使用rails 3.2.13、Oracle 11.2.0.3.0和activerecord-Oracle_增强型适配器(1.4.2),我的控制器中有以下功能: def show if params.has_key?('user_id') @user = User.find(params[:user_id]) else @user = current_user end

我最近开始将我的应用程序从使用sqlite移动到Oracle,并开始遇到以下问题:

使用rails 3.2.13、Oracle 11.2.0.3.0和activerecord-Oracle_增强型适配器(1.4.2),我的控制器中有以下功能:

def show
    if params.has_key?('user_id')
      @user = User.find(params[:user_id])
    else
      @user = current_user
    end
    @user_id = @user.id

    @activity_date = Date.parse(params[:id])
    #@activity_date = Activity.all.first.activity_date

    @activities = Activity.where("user_id = ? AND activity_date = ?", @user.id, @activity_date)
    logger.warn "----- count is #{@activities.count} ------"
return
  • 应用程序精确查找0条记录(根据记录器输出,并使用@user和@activity\u date的适当值)

  • development.log将生成的查询报告为:

    从“活动”中选择计数(*),其中(用户id=10594,截止日期(活动日期)=截止日期('2013-06-05','YYYY-MM-DD HH24:MI:SS'))

如果我从SQL*Plus运行这个查询,我会得到我期望的4条记录 -因此,AR返回的结果与AR正在向我的日志报告的查询返回的结果之间似乎存在差异

  • 此外,如果我在where调用之前手动设置日期,比如

    @活动\日期=活动.all.first.activity\日期

如果第一个活动日期恰好是“正确”的活动日期,Rails将返回所有4行,因此控制台和应用程序指向同一个数据库

据我所知:

  • Rails正在生成有效的查询,因此进入.where方法的值是OK的
  • 当从SQL*Plus运行时,所述查询返回“正确”数量的结果**
  • 控制台和应用程序指向相同的数据库
  • 但Rails似乎“看到”了错误数量的结果
发生什么事了?我的头发都快没了

根据下面David Aldridge的建议,编辑删除了“关于活动日期的拜访”占位符;仍然没有得到正确的结果集。 根据David的建议编辑

 @user_id=10594
 @activity_date=Date.parse('2013-06-13')

####### **Returned wrong set of results**
####### Note class of @activity_date is Date
    bundler-0.9.24 :083 > @activity_date.class
    => Date 

    bundler-0.9.24 :084 > Activity.where("user_id = ? AND activity_date = ?", @userid, @activity_date).explain
      Activity Load (1.8ms)  SELECT "ACTIVITIES".* FROM "ACTIVITIES" WHERE (user_id = NULL AND activity_date = TO_DATE('2013-06-13','YYYY-MM-DD HH24:MI:SS'))
      EXPLAIN (7.8ms)  EXPLAIN PLAN FOR SELECT "ACTIVITIES".* FROM "ACTIVITIES" WHERE (user_id = NULL AND activity_date = TO_DATE('2013-06-13','YYYY-MM-DD HH24:MI:SS'))

####### **Returned right set of results**
    bundler-0.9.24 :089 > @activity_date=Activity.all.first.activity_date
      Activity Load (1.5ms)  SELECT "ACTIVITIES".* FROM "ACTIVITIES" 
    => Wed, 05 Jun 2013 04:00:00 UTC +00:00 

#### Note class of @activity_date is different from above**

    bundler-0.9.24 :090 > @activity_date.class
    => ActiveSupport::TimeWithZone 
    bundler-0.9.24 :091 > Activity.where("user_id = ? AND activity_date = ?", @userid, @activity_date).explain
**And note generated query includes a time specification whereas previous query did not**
      Activity Load (2.7ms)  SELECT "ACTIVITIES".* FROM "ACTIVITIES" WHERE (user_id = NULL AND activity_date = TO_DATE('2013-06-05 04:00:00','YYYY-MM-DD HH24:MI:SS'))
已解决 当我创建activity_date字段时,我使用了date.civil。我忽略了Oracle调用它的“日期”类型实际上也包含一个时间组件。p>
由于Date.civil不带时区,因此我存储的activity_Date本质上是一个DateTime,由本地时区偏移(因为Date.civil不带时区)。由于我的应用程序忽略了实际时间,因此我通过使用DateTime.civil而不是date.civil计算activity_date来解决这个问题。感谢David Aldridge的帮助,很抱歉我没有足够的代表投票支持他。

活动日期列实际上是日期,还是需要转换为日期的字符串

如果是前者,则“截止日期”是错误的,不应出现

@activities = Activity.where("user_id = ? AND activity_date = ?", @user.id, @activity_date)
它可以在一个环境中工作而不能在另一个环境中工作的原因是,对于数据库或会话,环境的nls_date_参数值不同

这里一个有用的诊断可能是explain计划,如果rails使用DBMS_XPlan来获取该计划,它应该显示隐式数据转换。您应该能够通过以下控制台获取计划:

Activity.where("user_id = ? AND activity_date = ?", @user.id, @activity_date).explain
在SQL*Plus中运行查询,然后运行:

select * from table(dbms_xplan.display);
。。。应该为您提供SQL*Plus正在使用的计划


如果您在问题中发布它们,可能会帮助将来遇到问题的人。

活动日期列的类型为日期。我尝试了两种方法-在TO_日期调用中包装和不包装activity_date占位符,这似乎没有任何区别:两种方法都返回相同的结果集。谢谢你,大卫。这对问题有影响吗?如果您将谓词提供为where(:user\u id=>@user\u id,:activity\u date=>@activity\u date)…怎么样?如果没有区别,请尝试提取解释计划并发布它们好吗?它将显示Optimizer正在应用的任何查询转换,或者最新转换格式图片中的任何扩展。删除TO_DATE调用确实会对查询产生影响,但我(仍然)没有得到任何回报(我认为这是我第一次编写它的方式)。按照您的建议提供谓词不会更改生成的查询,也不会更改返回的结果。我注意到Activity.all.first.Activity_date(它确实有效)返回的类与date.parse不同,我想知道这是否是我的问题所在。我对activerecord创建的to_date()有点怀疑,其中数据本身是YYYY-MM-DD,但日期格式图片包含时间组件。不过我已经测试过了,看起来还可以。是否可能存在activity_date的时间组件?我注意到activity.all.first.activity_date属于类“ActiveSupport::TimeWithZone”(有效),而date.parse返回类date的对象(似乎不起作用)…提交TimeWithZone值时查询是什么样子的?