转换为 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

将未维护的 ActiveRecord 适配器强制转换为 Rails 版本 6

如何将 ActiveRecord 模型数组转换为 CSV?