You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否执行原生SQL查询、使用预处理语句且不使用ActiveRecord::Relation::QueryAttribute?

嘿,针对你提出的两个Rails数据库操作问题,我整理了实用的解决方案,完全避开你不想用的ActiveRecord::Relation::QueryAttribute类:

Rails原生SQL与Upsert解决方案(避开ActiveRecord::Relation::QueryAttribute)

问题1:执行原生SQL查询与预处理语句(不依赖ActiveRecord::Relation::QueryAttribute)

当然可以!你直接借助ActiveRecord的数据库连接对象的底层方法就能实现,完全不需要用到ActiveRecord::Relation::QueryAttribute。这里有两种常用方式:

方式一:使用prepare + execute

这种方式适合重复执行的查询,手动创建预处理语句,绑定参数后执行:

# 创建预处理语句(PostgreSQL用$1/$2占位符,MySQL用?)
stmt = ActiveRecord::Base.connection.prepare("get_user_by_id", "SELECT * FROM users WHERE id = $1")

# 执行语句并传入参数
user_results = stmt.execute(current_user_id)

# 记得用完关闭语句(可选,连接回收时会自动处理,但显式关闭更规范)
stmt.close

方式二:使用exec_query直接执行带参数的SQL

如果是一次性查询,用exec_query更简洁,参数通过数组传递,数据库会自动处理预处理:

results = ActiveRecord::Base.connection.exec_query(
  "SELECT name, email FROM users WHERE created_at > $1",
  "Fetch Recent Users", # 可选的查询名称,用于日志
  [[nil, 7.days.ago]]  # 参数数组:每个元素是[类型标识, 值],nil让数据库自动推断类型
)

这两种方法都是直接和数据库驱动交互,参数绑定过程完全绕开了ActiveRecord::Relation::QueryAttribute类。


问题2:带预处理语句的Upsert操作(ON CONFLICT DO NOTHING)

你提到的ON CONFLICT语法(PostgreSQL专属,MySQL用ON DUPLICATE KEY UPDATE)可以通过数据库连接的底层方法实现,同样不需要依赖ActiveRecord::Relation::QueryAttribute。这里推荐两种可靠的写法:

方式一:用prepare + execute实现可复用的Upsert

如果需要多次执行相同的Upsert逻辑,预处理语句能提升性能:

# 创建Upsert预处理语句
upsert_stmt = ActiveRecord::Base.connection.prepare(
  "upsert_foos",
  "INSERT INTO foos (thing_id, bar_id) VALUES ($1, $2) ON CONFLICT (thing_id, bar_id) DO NOTHING"
)

# 执行Upsert,传入具体参数
upsert_stmt.execute(1, 2)
# 也可以批量传入参数(如果驱动支持)
upsert_stmt.execute(3, 4)

# 关闭语句
upsert_stmt.close

方式二:用exec_insert一次性执行Upsert

如果是单次操作,exec_insert更方便,它会自动处理参数绑定,还能返回插入结果的主键(如果需要的话):

# 定义参数
thing_id = 1
bar_id = 2

# 执行Upsert
ActiveRecord::Base.connection.exec_insert(
  "INSERT INTO foos (thing_id, bar_id) VALUES ($1, $2) ON CONFLICT (thing_id, bar_id) DO NOTHING",
  "Upsert Foo", # 日志用的查询名称
  [[nil, thing_id], [nil, bar_id]] # 参数数组,nil自动推断类型
)

这两种写法都直接使用数据库连接的原生预处理能力,完全不需要借助ActiveRecord::Relation::QueryAttribute来包装参数。


内容的提问来源于stack exchange,提问作者John Bachir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:34:39