转换为 ActiveRecord 查询(火鸟数据库)时导致错误的原始 SQL 查询
Posted
技术标签:
【中文标题】转换为 ActiveRecord 查询(火鸟数据库)时导致错误的原始 SQL 查询【英文标题】:Raw SQL Query that causes error when translated to ActiveRecord Query (Firebird Database) 【发布时间】:2020-09-16 18:56:16 【问题描述】:我正在尝试做一个相当简单的查询,该查询涉及通过特定列获取两个日期之间的所有记录。
原始 SQL 在 ISQL Firebird 中运行良好:
SELECT * FROM OPS_HEADER
WHERE PB_BOL_DT
BETWEEN '2020-09-01' AND '2020-09-10';
这是我的 ActiveRecord 转换:
OpsHeader.where('pb_bol_dt BETWEEN 2020-09-01 AND 2020-09-10')
上面这行给了我这个错误:
expression evaluation not supported expression evaluation not supported Only one operand can be of type TIMESTAMP
我可能把它转换错了,但它确实似乎是这样做的确切方法......我不知道为什么它给我带来这么多麻烦。
【问题讨论】:
日期文字周围的引号去哪儿了?为什么不OpsHeader.where(pb_bol_dt: '2020-09-01' .. '2020-09-10')
或OpsHeader.where('pb_bol_dt between ? and ?', '2020-09-01', '2020-09-10')
或OpsHeader.where('pb_bol_dt between :lower and :upper', lower: '2020-09-01', upper: '2020-09-10')
?
我已经离开游戏这么久了......这是一个很好的复习。如果您愿意,请将其作为答案放在下面,我会接受。此外,就性能而言,这些方法的工作方式是否相似?
使用 fbprofiler.sf.net 检查您的数据库实际从您的应用程序接收到的内容。需要 Firebird 2.5+ (TraceAPI)
【参考方案1】:
您在日期文字上缺少引号,您想从以下开始:
OpsHeader.where(%q(pb_bol_dt BETWEEN '2020-09-01' AND '2020-09-10'))
但是可以通过传递一个范围来让 ActiveRecord 构建一个 BETWEEN:
OpsHeader.where(pb_bol_dt: '2020-09-01' .. '2020-09-10')
并让 AR 处理报价。您还可以使用位置或命名占位符分别传递端点:
OpsHeader.where('pb_bol_dt between ? and ?', '2020-09-01', '2020-09-10')
OpsHeader.where('pb_bol_dt between :lower and :upper', lower: '2020-09-01', upper: '2020-09-10')
所有这些最终都会向数据库发送相同的 SQL,唯一的区别是构建后三个查询所需的少量字符串处理和类型处理。
【讨论】:
感谢您的回答!快速提问;如果我想在同一天的两个时间戳之间进行检查怎么办?会是这个样子吗?pb_status_time: '2020-09-01 00:00:00' .. '2020-09-01 24:00:00')
?
应该可以,或者您可以使用一系列实时实例。以上是关于转换为 ActiveRecord 查询(火鸟数据库)时导致错误的原始 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章
ActiveRecord Rails将created_at时间戳转换为查询所在的时区
如何将此查询转换为ActiveRecord(Rails 5)
如何将 DAO 查询转换为 Yii2 ActiveRecord。如何从连接表中选择和使用特定列
使用 Arel 进行嵌套集和连接查询并转换为 ActiveRecord::Relation