gpt4 book ai didi

ruby-on-rails - 如何将数组作为绑定(bind)变量传递给 Rails/ActiveRecord 原始 SQL 查询?

转载 作者:行者123 更新时间:2023-12-05 07:26:13 25 4
gpt4 key购买 nike

我需要像这样将一个 id 数组传递到我的原始 sql 查询中:

select offers.* from offers where id in (1,2,3,4,5)

真正的查询包括很多连接和聚合函数,不能使用 Arel 表达式或 ActiveRecord 模型方法编写,如 Offer.where(id: [...])。我正在寻找如何在原始查询中使用绑定(bind)变量。

我不想将 id 插入字符串,而是像这样使用绑定(bind)变量(伪代码):

ActiveRecord::Base.connection.select_all("select offers.* from offers where id in (:ids)", {ids: [1,2,3,4,5]})

但是,我找不到任何解决方案来执行此操作。来自 this我在 ActiveRecord 代码中收到了一条关于相关测试用例的评论 following示例:

sub   = Arel::Nodes::BindParam.new
binds = [Relation::QueryAttribute.new("id", 1, Type::Value.new)]
sql = "select * from topics where id = #{sub.to_sql}"

@connection.exec_query(sql, "SQL", binds)

我已经尝试过这种方法,但它根本不起作用,我的“?”没有被实际值取代。

我正在使用 Rails 5.1.6 和 MariaDB 数据库。

最佳答案

您可以使用 arel 以更简单的方式完成此操作. (而且它使代码比 SQL 字符串更易于维护)

offers = Arel::Table.new('offers') 
ids = [1,2,3,4,5]
query = offers.project(Arel.star).where(offers[:id].in(ids))
ActiveRecord::Base.connection.exec_query(query.to_sql)

这将导致以下 SQL

SELECT 
[offers].*
FROM
[offers]
WHERE
[offers].[id] IN (1,2,3,4,5)

执行后您将收到 ActiveRecord::Result对象 with 通常最容易通过调用 to_hash 来处理每个结果行将变成 Hash{column_name => value}

但是,如果您使用的是 rails 和 Offer那么是一个真正的模型:

Offer.where(id: ids)

将产生相同的查询并返回 ActiveRecord::Relation收藏Offer通常更可取的对象。

更新

看来您需要启用 prepared_statements在 mysql2 ( mariadb ) 中使用绑定(bind)参数,可以这样做:

default: &default
adapter: mysql2
encoding: utf8
prepared_statements: true # <- here we go!

请注意以下代码: https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb#L115

https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L40

https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb#L630

https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb#L30

正如你在最后一段代码中看到的exec_query忽略 bind_params如果prepared_statements已关闭(这似乎是 mysql2 适配器的默认设置)。

关于ruby-on-rails - 如何将数组作为绑定(bind)变量传递给 Rails/ActiveRecord 原始 SQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54518294/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com