【问题标题】:Calling MySQL stored procedure in ROR 4在 ROR 4 中调用 MySQL 存储过程
【发布时间】:2021-08-27 00:15:46
【问题描述】:

那里的例子很少,但没有一个非常清楚(或旧版本)。

我想调用 MySQL 过程并检查返回状态(在 rails 4.2 中)。我看到的最常见的方法是调用result = ActiveRecord::Base.connection.execute("call example_proc()"),但是在某些地方人们写有准备好的方法result = ActiveRecord::Base.connection.execute_procedure("Stored Procedure Name", arg1, arg2)(但是它没有编译)。

那么调用和获取 MySQL 过程状态的正确方法是什么?

编辑:

以及如何安全地发送参数,第一个参数是整数,第二个字符串和第三个布尔值?

【问题讨论】:

  • 一般来说,您应该能够在给定模型的常规whereselect 方法中调用存储过程:YourModel.where("YOUR_PROC(?, ?)", var1, var2) 不是更简单吗?或者你有一些额外的要求?
  • 如你所见,你们都有不同的方法。如果execute_procedure 已被弃用,我猜是因为某些原因(更好的方法/新方法)。底线我想要最正确的方法,之后进行程序验证(针对警告和错误)。

标签: mysql ruby-on-rails ruby-on-rails-4 rails-activerecord mysql-5.5


【解决方案1】:

Rails 4 ActiveRecord::Base 不支持 execute_procedure 方法,但 result = ActiveRecord::Base.connection 仍然有效。即

result = ActiveRecord::Base.connection.execute("call example_proc('#{arg1}','#{arg2}')")

【讨论】:

  • 虽然它可以工作,但我不确定它是否安全。首先,如果其中一个 args 包含',则程序会被破坏。其次,如果其中一个参数是 text'); delete from tags; - 如何安全地发送此参数(第一个是整数,第二个字符串和第三个布尔值)?
【解决方案2】:

你可以试试下面的毗湿奴方法

你也可以试试

ActiveRecord::Base.connections.exec_query("call example_proc('#{arg1}','#{arg2}')")

here is the document

【讨论】:

    【解决方案3】:

    一般来说,您应该能够在给定模型的常规 whereselect 方法中调用存储过程:

    YourModel.where("YOUR_PROC(?, ?)", var1, var2)
    

    至于您的评论“最重要的是,我想要最正确的程序验证方法(用于警告和错误)”,我想这始终取决于您实际想要实现的内容以及您希望代码的可读性。

    例如,如果您想返回 YourModel 属性的行,那么将上述语句与where 方法一起使用可能会更好。另一方面,如果你写了一些 sql 适配器,那么你可能想要下到 ActiveRecord::Base.connection.execute 级别。

    顺便说一句,这里应该提到一些关于存储过程性能的东西。在一些数据库中,数据库会在存储过程的第一次运行时进行存储过程优化。但是,您传递给第一次运行的参数可能不是以后会更频繁地运行。因此,您的存储过程可能会以针对您的情况的“非最佳”方式自动优化。它可能会也可能不会以这种方式发生,但在使用带有动态参数的存储过程时应该考虑这一点。

    【讨论】:

    • 绑定变量是为了处理这个问题而设计的。至于验证部分 - 因为它是一个过程(不返回值),唯一的验证是:通过/失败/警告。
    【解决方案4】:

    我相信您已经尝试了许多其他解决方案,但遇到了一些或其他错误,主要是“不同步”或“关闭连接”错误。每次您尝试执行查询时,都会出现这些错误。我们需要像每次连接都是新的那样解决这个问题。这是我没有抛出任何错误的解决方案。

    #checkout a connection for Model
    conn = ModelName.connection_pool.checkout
    
    #use the new connection to execute the query
    @records = conn.execute("call proc_name('params')")
    
    #checkout the connection
    ModelName.connection_pool.checkin(conn)
    

    其他方法对我来说失败了,可能是因为 ActiveRecord 连接被自动处理以检查和检查每个线程。当我们的方法尝试检查一个连接只是为了执行 SP 时,它可能会发生冲突,因为在方法启动时会有一个活动的连接。

    所以想法是手动#checkout 模型的连接,而不是池中的线程/函数,并在工作完成后#checkin。这对我很有用。

    【讨论】:

      猜你喜欢
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 2017-04-23
      • 2016-05-03
      • 2013-05-18
      相关资源
      最近更新 更多