我可以执行原始 SQL 查询、利用准备好的语句而不使用 ActiveRecord::Relation::QueryAttribute 吗?

2023-12-24

我想做一个upsert https://www.postgresql.org/docs/10/static/sql-insert.html#SQL-ON-CONFLICT。 Rails 还不支持这个。查询是这样的:

INSERT INTO foos (thing_id, bar_id) VALUES (1, 2)
ON CONFLICT (thing_id, bar_id) DO NOTHING

我可以轻松做到这一点self.class.connection.execute or exec_insert。但我还想利用准备好的声明。我想我可以这样做:

thing_id = ActiveRecord::Relation::QueryAttribute.new("thing_id", thing.id, ActiveRecord::Type::Integer.new)
bar_id = ActiveRecord::Relation::QueryAttribute.new("bar_id", id, ActiveRecord::Type::Integer.new)

self.class.connection.exec_insert(<<-SQL, nil, [thing_id, bar_id])
  INSERT INTO foos (thing_id, bar_id) VALUES ($1, $2)
  ON CONFLICT (thing_id, bar_id) DO NOTHING
SQL

但是当我尝试这个时,似乎没有创建准备好的语句。

我尝试过这种风格:

query = <<-SQL
  INSERT INTO foos (thing_id, bar_id) VALUES ($1, $2)
  ON CONFLICT (thing_id, bar_id) DO NOTHING
SQL

connection = ActiveRecord::Base.connection.raw_connection
connection.prepare('some_name', query)
st = connection.exec_prepared('some_name', [ thing.id, id ])

它确实创建了一个准备好的声明。但是,第二次运行时,postgres 抱怨创建了一个同名的准备好的语句。因此,rails 的预准备语句管理发生在高于此的级别,我无法在这里利用它。我必须在这里手动管理它。我不相信我能正确地做到这一点,即使我能做到,它也会很冗长。

execute和朋友不接受("foo=?", 1)api 那个where接受。

有什么方法可以利用rails的自动预准备语句管理来处理原始SQL吗?


#exec_query接受一个可选的关键字参数,prepare,默认为 false。看看方法定义 https://github.com/rails/rails/blob/379d98dcd40f28fd959f42958d662b5416171eea/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb#L80 (and here https://github.com/rails/rails/blob/379d98dcd40f28fd959f42958d662b5416171eea/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L586).

给出下表定义:

CREATE TABLE foos (
    thing_id INT,
    bar_id INT,
    UNIQUE (thing_id, bar_id)
);

我测试了以下内容:

conn = ActiveRecord::Base.connection
stmt = 'INSERT INTO foos (thing_id, bar_id) VALUES ($1, $2) ' \
       'ON CONFLICT (thing_id, bar_id) DO NOTHING'

# "Old" bind parameters
binds = [[nil, 1], [nil, 2]]
conn.exec_query stmt, 'SQL', binds, prepare: true
conn.exec_query stmt, 'SQL', binds, prepare: true

# "New" bind parameters
type  = ActiveModel::Type::Integer.new limit: 4
binds = [
  ActiveRecord::Relation::QueryAttribute.new('thing_id', 1, type),
  ActiveRecord::Relation::QueryAttribute.new('bar_id',   2, type)
]
conn.exec_query stmt, 'SQL', binds, prepare: true
conn.exec_query stmt, 'SQL', binds, prepare: true

这两种绑定参数样式都适用于 ActiveRecord 5.2.0 和 pg 1.0.0。使用相同值的多个 INSERT 语句最终会导致仅插入一行且不会引发错误。我检查了 Postgres 日志,只有一个“解析”(在第一个 INSERT 之前),因此看来准备好的语句机制正在正确使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以执行原始 SQL 查询、利用准备好的语句而不使用 ActiveRecord::Relation::QueryAttribute 吗? 的相关文章

  • 如何将 CarrierWave 文件迁移到新的存储机制?

    我有一个 Ruby on Rails 站点 其中包含使用 CarrierWave 进行文件处理的模型 当前使用本地存储 我想开始使用云存储 并且需要将现有的本地文件迁移到云端 我想知道是否有人可以指出这样做的方法 使用模型属性的好处是 它允
  • 如何将 Google Data Studio 连接到 AWS RDS Postgres 实例?

    当我在 Data Studio 中创建新数据源时 系统会提示我输入客户端 服务器证书以建立安全连接 我在哪里可以获取此客户端证书和密钥 如何允许 Google Data Studio 连接到我的 RDS 实例 请执行下列操作 Add the
  • 多步ActiveRecord的模型验证

    考虑具有以下字段的用户模型 名字 必填 姓氏 必填 电子邮件 必填 要求输入密码 电话 必填 大小 10 位数字 地址 必填 以及包含以下步骤的多步骤注册表单 第一步 包含 名字 姓氏 和 电子邮件 字段 第二步输入密码 电话和地址 您将如
  • REASSIGN OWNED BY 为 1 个指定数据库

    我想使用以下命令更改一个特定数据库中所有表的所有者 REASSIGN OWNED BY postgres TO myuser 但它显示 ERROR cannot reassign ownership of objects owned by
  • 默认更新嵌套属性

    我尝试更新 iProduction 这是生产中的嵌套表单 但此行出现参数错误 参数数量错误 0 代表 1 生产 update iproducts attributes cow id cow 我的创作动作制作 def create produ
  • Postgresql 中的 id 列位置重要吗?

    我正在测试删除主键列 id 的迁移 我想使用外键作为主键 当我运行并恢复迁移时 我看到表的状态是相同的 只是 id 列现在是最后一个 它会以任何方式改变我的数据库的行为吗 我是否应该费心去恢复迁移恢复代码中的列顺序 理论上一切都应该没问题
  • 在同一个表上组合两个 SQL SELECT 语句

    我想结合这两个 SQL 查询 SELECT FROM Contracts WHERE productType RINsell AND clearTime IS NULL AND holdTime IS NOT NULL ORDER BY g
  • Rspec 控制器测试,传递 JSON 参数

    我试图实现以下目标 在 RSpec 控制器测试中创建 POST json 请求 并向其传递参数 这是我的代码 it returns access token do post login email bla password bla1 for
  • 使用 Devise 和 Rails 从 Twitter Oauth 获取电子邮件

    我已经设置了一个基本的 Rails 应用程序来使用 twitter oauth gem 和设计 并且已经能够登录用户 但是 我的问题是我现在已将我的应用程序列入白名单 并且我想在响应中收到用户的电子邮件 我已遵循 Twitter 端的所有必
  • 将文件传递给活动作业/后台作业

    我通过标准文件输入接收请求参数中的文件 def create file params file upload Upload create file file filename img png end 但是 对于大型上传 我想在后台作业中执行
  • Rails - 使用 %W

    我有以下效果很好的 def steps w hello billing confirmation end steps first 但我想这样做 def step title w Upload a photo Billing Info Con
  • 操作错误:游标“_django_curs_”不存在

    我们有一个由 django postgresql 和 heroku 提供支持的在线商店 Web 应用程序 对于特定的活动 您可以将活动视为要购买的产品 我们已成功售出 10 000 份以上的副本 然而 根据我们的 Sentry 报告 我们的
  • Postgres、更新和锁定顺序

    我正在研究 Postgres 9 2 有 2 个更新 每个更新都有自己的事务 一个看起来像 UPDATE foo SET a 1 WHERE b IN 1 2 3 4 另一个也类似 UPDATE foo SET a 2 WHERE b IN
  • 如何在数据库中存储年月?

    是否有在数据库中存储年份和月份的标准方法 我需要根据月份和年份制作一些报告 我无法使用日期和函数实时提取月份 因为表很大 所以我需要预处理 我会和 Michael 的建议是什么 https stackoverflow com a 81694
  • 在 Postgres 中的数组字段上应用聚合函数?

    是否可以对整数 字段 或其他数字数组 中的所有值应用聚合 如 avg stddev CREATE TABLE widget measurement integer insert into widget measurement values
  • Rails 应用程序在模型间保存方面遇到问题

    我正在开发一个从网站下载元标签并然后保存的应用程序 下载发生在一个名为Site 我想将下载的机器人元标签保存到一个名为的模型中robots tag它通过一个名为的连接表连接到站点meta tag sites 但是我在站点模型中编写的用于执行
  • i18n:特定型号的错误消息本地化

    我可以为每个验证本地化错误消息 但如何为特定模型创建错误 普通的语言环境如下所示 en mongoid errors messages taken It is already taken 但我想更改消息user model en mongo
  • 更新plpgsql中触发器函数中的多列

    给出以下架构 create table account type a id SERIAL UNIQUE PRIMARY KEY some column VARCHAR create table account type b id SERIA
  • 为什么对参数哈希进行切片会在批量分配时带来安全问题?

    通过批量分配来预防安全风险的官方方法是使用属性可访问 http api rubyonrails org classes ActiveModel MassAssignmentSecurity ClassMethods html 然而 一些程序
  • Postgresql插入触发器设置值

    假设在 Postgresql 中 我有一个表T它的一栏是C1 我想在新记录添加到表中时触发一个函数T 该函数应该检查列的值C1在新记录中 如果它为 null 空 则将其值设置为 X 这可能吗 您需要触发器是正确的 因为为列设置默认值对您不起

随机推荐