从Ruby中调用MySQL存储过程是否可行?

5

当我尝试从Rails调用存储过程时,出现以下异常:

ActiveRecord::StatementInvalid: Mysql::Error: PROCEDURE pipeline-ws_development.match_save_all can't return a result set in the given context: call match_save_all()
    from /Users/otto/Projects/Futures/src/pipeline-ws/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:150:in `log'
    from /Users/otto/Projects/Futures/src/pipeline-ws/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:281:in `execute'
    from (irb):3

以下是您需要翻译的内容:

Rails Wiki中有一篇页面讨论了一个解决MySQL适配器问题的补丁,但它已经过时,似乎不再起作用。

配置代码正确启用了存储过程,但仍存在连接在存储过程调用后失去同步的问题,并且新的call_sp方法不再起作用。

有没有建议如何使其正常工作?

这是我使用的代码:

ActiveRecord::Base.connection("call storedproc()")

无论storedproc()返回结果与否,它都会抛出相同的异常。
3个回答

2

1

将过程包装在函数中是否可行?如果 Ruby 由于没有返回行而出现错误(...can't return a result set in the given context...),则可以尝试使用以下方法解决:

DELIMITER $
CREATE PROCEDURE tProc() BEGIN SET @a = 'test'; END; $
CREATE FUNCTION tFunc() RETURNS INT BEGIN CALL tProc(); RETURN 1; END; $
DELIMITER ;
SELECT tFunc() FROM DUAL; >> 1
SELECT @a FROM DUAL; >> 'test'

但实际上,这并不是一个非常可扩展的解决方案。

跟进:我对 Ruby/ActiveRecord 不太熟悉,但这个示例确实有效

ActiveRecord::Base.establish_connection(authopts)
class TestClass < ActiveRecord::Base end
test_class = TestClass.new puts %{#{test_class.connection.select_one('SELECT tFunc() AS tf FROM DUAL')}} >> tf1

使用 CALL tProc() 会导致类似于您遇到的错误。


你的例子可行,但是我们的存储过程会出现“ERROR 1415 (0A000): Not allowed to return a result set from a function”的错误。我打算和编写它们的人交谈,看看是否可以像你的例子一样重写它们来返回结果。 - Otto
1
这使我们向前迈进了一步,但我们仍有几个过程需要返回大量数据,这些数据无法在变量中处理。 - Otto
我已经接受了,因为这似乎是目前最好的解决方案。仍然存在返回大量数据的问题,但已经过去几天了,没有人提出更好的解决方案。我认为,如果不修复MySQL适配器,这是不存在的。 - Otto
我有点不清楚 - 存储过程能返回数据吗?我相当确定 MySQL 中的存储过程不会返回任何东西。你能详细说明一下吗? - kyle

1
你是否正在使用 ActiveRecord::Base.connection.execute?这个方法应该允许你执行一些在 Active Record 包装器中不被原生支持的任意 SQL 语句。

1
这就是我正在使用的,但我遇到了那个异常。 - Otto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接