Простая хранимая процедура в MySQL:
CREATE PROCEDURE `proc01`()
BEGIN
SELECT * FROM users;
END
Запускает консоль Rails:
$ script/console
Loading development environment (Rails 2.3.5)
>> User.connection.execute("CALL proc01")
=> #<Mysql::Result:0x10343efa0>
Выглядит хорошо. НО, вызов вызова одной и той же хранимой процедуры через существующее соединение приведет к ошибке Команды не синхронизируются:
>> User.connection.execute("CALL proc01")
ActiveRecord::StatementInvalid: Mysql::Error: Commands out of sync; you can't run this command now: CALL proc01
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract_adapter.rb:219:in `log'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.5/lib/active_record/connection_adapters/mysql_adapter.rb:323:in `execute'
from (irb):2
Ошибка может быть очищена с помощью "перезагрузки!". команды в консоли:
>> reload!
Reloading...
=> true
>> User.connection.execute("CALL proc01")
=> #<Mysql::Result:0x1033f14d0>
>>
Как я могу вызвать хранимую процедуру MySQL из Rails?
EDIT:
-
Использование ActiveRecord::Base.connections.exec_query()
- это насколько я могу сказать лучше MUCH, потому что он возвращает массив хэшей, как и следовало ожидать, а ActiveRecord::Base.connections.execute
- нет.
-
Пожалуйста, прочитайте приведенное выше изменение, я оставляю ниже для справки.
Пока я понимаю, что этот вопрос довольно старый, и потому что ссылки ohho, опубликованные, имеют 404'd, у меня была такая же ошибка в последнее время.
Мне удалось исправить это, выполнив следующие действия:
result = ActiveRecord::Base.connection.execute("call example_proc()")
ActiveRecord::Base.clear_active_connections!
После того, как вы очистили соединения, вы можете запускать любые другие запросы, которые, как и раньше, потерпели бы неудачу при попытке доступа к базе данных через рельсы или другую сохраненную процедуру.
http://apidock.com/rails/v3.2.13/ActiveRecord/Base/clear_active_connections%21/class
- EDIT:
Также стоит упомянуть, что не следует сохранять соединение ActiveRecord в переменной как в leente post на этой ссылке
"Не кешируйте его!
Не храните соединение в переменной, потому что другой поток может попытаться использовать его, когда он уже проверен обратно в пул соединений. См.: ConnectionPool"
connection = ActiveRecord::Base.connection #WRONG
threads = (1..100).map do
Thread.new do
begin
10.times do
connection.execute("SELECT SLEEP(1)") # WRONG
ActiveRecord::Base.connection.execute("SELECT SLEEP(1)") # CORRECT
end
puts "success"
rescue => e
puts e.message
end
end
end
threads.each(&:join)