Подготовленное заявление о Postgresql в Rails
Сейчас я нахожусь в процессе перехода с SQLite на Postgresql, и я столкнулся с этой проблемой. Следующий подготовленный оператор работает с SQLite:
id = 5
st = ActiveRecord::Base.connection.raw_connection.prepare("DELETE FROM my_table WHERE id = ?")
st.execute(id)
st.close
К сожалению, он не работает с Postgresql - он выдает исключение в строке 2. Я искал решения и наткнулся на это:
id = 5
require 'pg'
conn = PG::Connection.open(:dbname => 'my_db_development')
conn.prepare('statement1', 'DELETE FROM my_table WHERE id = $1')
conn.exec_prepared('statement1', [ id ])
Это не удается в строке 3. Когда я печатаю исключение, как это
rescue => ex
бывший содержит это
{"connection":{}}
Выполнение SQL в командной строке работает. Есть идеи, что я делаю не так?
Заранее спасибо!
2 ответа
Если вы хотите использовать prepare
тогда вам нужно сделать пару изменений:
Драйвер PostgreSQL хочет видеть пронумерованные заполнители (
$1
,$2
,...) не ставьте вопросительные знаки, и вам нужно дать вашему подготовленному заявлению имя:ActiveRecord::Base.connection.raw_connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1")
Последовательность вызова
prepare
с последующимexec_prepared
:connection = ActiveRecord::Base.connection.raw_connection connection.prepare('some_name', "DELETE FROM my_table WHERE id = $1") st = connection.exec_prepared('some_name', [ id ])
Вышеупомянутый подход работает для меня с ActiveRecord и PostgreSQL, ваш PG::Connection.open
версия должна работать, если вы подключаетесь правильно.
Еще один способ сделать цитату самостоятельно:
conn = ActiveRecord::Base.connection
conn.execute(%Q{
delete from my_table
where id = #{conn.quote(id)}
})
Это то, что ActiveRecord обычно делает за вашей спиной.
Непосредственное взаимодействие с базой данных, как правило, немного мешает Rails, так как люди из Rails не думают, что вы должны когда-либо это делать.
Если вы действительно пытаетесь удалить строку без помех, вы можете использовать delete
:
удалять()
[...]
Строка просто удаляется с помощью SQL
DELETE
заявление о первичном ключе записи, и никакие обратные вызовы не выполняются.
Так что вы можете просто сказать это:
MyTable.delete(id)
и вы отправите простой delete from my_tables where id = ...
в базу данных.
В дополнение к уже принятому ответу для тех, кто готовит запросы Google в Rails для пользовательских запросов, вот более простой способ сделать это через существующий интерфейс ActiveRecord (пример для Postgresql):
ActiveRecord::Base.connection.exec_query("select * from table_name where id = $1",
"example_query", [1], prepare: true)
А если поставитьbinding.pry
, вы увидите, что подготовленный оператор действительно создан:
ActiveRecord::Base.connection.exec_query('select * from pg_prepared_statements')
Ссылка: https://api.rubyonrails.org/v7.0.4.2/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html