【问题标题】:Stored procedures in Ruby on RailsRuby on Rails 中的存储过程
【发布时间】:2013-03-20 07:09:35
【问题描述】:

我是一个拥有 6 年经验的 .net 专家。最近我开始研究 ROR 项目,并意识到根本没有使用存储过程/sql 函数。在询问它时,我了解到这是一种常见的做法,通常团队中根本没有人编写 sql 查询,一切都是使用 ActiveRecord 完成的。

我搜索了任何可能的原因,但没有找到太多信息。所以我只是好奇地知道

  1. 不喜欢使用存储过程/sql 函数是常见的做法吗?
  2. 使用存储过程的优缺点是什么?

【问题讨论】:

    标签: mysql ruby-on-rails activerecord stored-procedures


    【解决方案1】:

    不喜欢使用存储过程/sql 函数是常见的做法吗?

    非常很常见,大多数 Rails 应用程序永远不需要使用 ActiveRecord 以外的任何东西。

    Rails 背后的主要理念之一是,今天工作产品推向市场比将“快速”产品推向市场更重要 6几个月后。你的产品几乎肯定永远不会流行到足以让性能成为问题的程度。如果这确实成为一个问题,您可以稍后支持性能方面,但当务之急是能够快速构建应用程序,并能够快速重构部分或全部以响应您的市场。

    使用存储过程的优缺点是什么?

    它们的编写速度较慢且更难更改,因此会增加您的开发成本。但是,它们可以更快地执行。

    【讨论】:

    • 我意识到这个线程已有 4 年零 1 天的历史,但存储过程“写起来很慢,更难改变”完全是谬论。当然,我遇到了这个线程,因为我也是一个 .Net 人,必须在 rails 网站上更新一个非常古老的 ruby​​。我的假设是存储过程在数据库中而不是在 Rails 中。如果它在 Rails 中,那么我会承认并说你可能是正确的。但是数据库中的 SP 非常简单。
    • 现在已经 6 年了,而且还在变化。但要加2美分。如果您在后端使用 Rails 之外的技术,同时又不是 Rails,将逻辑放在存储过程或触发器中将是集中逻辑的好方法。
    • 是的,这从来都不是一个伟大的设计理念(尽管不幸的是,由于网页设计社区的 SQL 技能很差,这是可以理解的)。存储过程可以神奇地简化极其复杂的查询。
    【解决方案2】:

    使用存储过程可能不是“rails 方式”,但它也曾经不是使用外键约束的“rails 方式”,我们都知道结果是一个非常糟糕的设计决策。

    所以我会采取“铁轨之路”与一粒盐。如果存储过程适合您,请使用它们。

    这就是我的工作。了解 ORM 通常不会真正“理解”存储过程而没有更深入的魔法,因此我避免直接​​使用它,而是创建一个封装存储过程的物化视图,然后将其呈现为常规表。正确设置后,这使得 ORM 可以更好地理解,同时仍然利用将数据库逻辑保留在它应该存在的层内的优势,即数据库,一个在数据处理方面总是优于 Web 框架的引擎。

    【讨论】:

      【解决方案3】:

      您可以从 Rails 中调用存储过程,但您将失去 ActiveRecord 的大部分优势,因为标准生成的 SQL 将不起作用。您可以使用本地数据库连接并调用它,但这将是一个泄漏的抽象。您可能需要考虑 DataMapper。

      取自>>Using Stored Procedures in Rails

      总而言之,它不是使用存储过程的“RAILS WAY”。

      【讨论】:

        【解决方案4】:

        不喜欢使用存储过程/sql 函数是常见的做法吗?

        没错。使用 Active Record 构建查询允许您在应用程序代码中管理它们。

        使用存储过程的优缺点是什么?

        优点:您可以在应用程序代码中隐藏复杂的查询逻辑。

        缺点:如果要重写过程,则必须创建并执行迁移。

        See this example on hiding logic in a database view, also applicable to procedures.

        优点示例:

        您需要选择在start_timeend_time 之间提供客房的所有酒店。每个酒店都有 total_rooms(整数属性)、hotel_times(定义酒店营业时间的实体)和一些预订(定义在酒店预订房间的用户的实体)。有些酒店很大,提供每日预订。其他酒店规模较小,按小时预订。您询问用户何时要预订,可以是日期或日期与时间。

        这涉及到一些连接和子查询,并且会创建一大段丑陋的 Active Record 代码。相反,您可以编写一个过程并像这样调用它:

        Hotel.find_by_sql ['SELECT * FROM hotels_available_between(?, ?)', start_time, end_time]
        

        将它包装在一个作用域中并获得更多的 ruby​​ 风格:

        class Hotel < ActiveRecord::Base
          scope :available_between, -> start_time, end_time do
            find_by_sql ['SELECT * FROM hotels_available_between(?, ?)', start_time, end_time]
          end
        end
        
        Hotel.available_between start_time, end_time
        

        【讨论】:

          猜你喜欢
          • 2023-04-01
          • 1970-01-01
          • 2011-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-15
          • 1970-01-01
          相关资源
          最近更新 更多