1

我正在尝试构建一个“提取一些数据并显示它”的应用程序。为了提取数据,我们有大量特定于站点的 oracle sql(存储过程、奇怪的表达式等等)。

我需要做的一种方法是创建 oracle 视图,然后将 activerecord 指向这些视图。但我宁愿将所有 SQL 放在一个地方——ruby 应用程序本身——而不是在 oracle 和 ruby​​ 中。我想在原始 SQL 选择子句上创建一个活动记录对象,然后能够使用所有常用的活动记录对象。

现在 - 我知道 Oracle SQL 支持这一点。让我们来:

select n.name_id, name, munge(n.name) as munged from name

通常你会创建一个视图 munged_name,一个类 MungedName,结果是

MungedName.like(:name , 'Foo%')

将(最终)生成如下所示的 SQL:

select T1.name_id, T1.name, T1.munged 
from munged_name as T1
where T1.name like 'Foo%'

然而,我想做的是让 ActiveRecord 使用 sql select 作为 FROM 子句中的子查询:

select T1.name_id, T1.name, T1.munged
from (select n.name_id, name, munge(n.name) as munged from name) as T1
where T1.name like 'Foo%'

直接把它塞进去——甲骨文会完美地优化它。这样,我的人想要做的所有奇怪的查询都在一个地方 - 在模型类定义中。

ActiveRecord 会这样做吗?我会继续寻找——看看我能不能在我在这里得到答案之前找到答案:)。

4

2 回答 2

0

我怀疑传递那个 SQL 片段应该可以工作。

MungedName.from("select n.name_id, name, munge(n.name) as munged from name").like(:name , 'Foo%')

但是您可能正在寻找更像 Ruby 的东西,因此您当然也可以from在 Arel 中生成该片段:

sql = Name.select([:name_id, :name, "munge(name)"]).to_sql
MungedName.from(sql).like(:name , 'Foo%')

我没有从命令行尝试任何这些。我怀疑我输入的内容是否会干净利落,但想法基本相同。Arel 可用于生成复杂的 SQL,并将该 SQL 输入到另一个 Arel 查询中。

我不确定这from部分,但我怀疑它会按预期工作。如果您查看方法源:

http://www.ruby-doc.org/gems/docs/a/arel-3.0.2/Arel/SelectManager.html#method-i-from

def from table
  table = Nodes::SqlLiteral.new(table) if String === table
  ...
end

SqlLiteral课程只是绕过任何引用或诸如此类的一种方式。

于 2013-10-09T02:20:13.583 回答
0

查看代码 - 它不起作用。没有 self.from= 方法。当您在 table_name 中插入原始 sql 时,它会引用它并将其视为表名。这很公平。activerecord ruby​​ 从头到尾都有一个东西'quoted_table_name'。

然而,associations.rb 上有一个有趣的评论:

# == Table Aliasing
#
# Active Record uses table aliasing in the case that a table is referenced multiple times
# in a join. If a table is referenced only once, the standard table name is used. The
# second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>.
# Indexes are appended for any more successive uses of the table name.

如果可以说服 activerecord 始终为 MungedName 模型设置别名(即使没有连接),并使用一些未引用的东西作为 from 的内容,可能会起作用。不过,我将不得不破坏图书馆。

于 2013-10-09T03:42:47.853 回答