我想做一个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吗?