Ruby on rails Rails/Oracle:ActiveRecord find从控制台和应用程序返回不同的结果
我最近开始将我的应用程序从使用sqlite移动到Oracle,并开始遇到以下问题: 使用rails 3.2.13、Oracle 11.2.0.3.0和activerecord-Oracle_增强型适配器(1.4.2),我的控制器中有以下功能: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
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'))
- 此外,如果我在where调用之前手动设置日期,比如 @活动\日期=活动.all.first.activity\日期
- Rails正在生成有效的查询,因此进入.where方法的值是OK的
- 当从SQL*Plus运行时,所述查询返回“正确”数量的结果**
- 控制台和应用程序指向相同的数据库
- 但Rails似乎“看到”了错误数量的结果
@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值时查询是什么样子的?