【问题标题】:When should a join table be used vs id in the table in Ruby on Rails databases何时应该使用连接表与 Ruby on Rails 数据库中的表中的 id
【发布时间】:2014-05-31 04:50:56
【问题描述】:

所以,我和一位同事正在争论如何为我们正在开发的网站设计数据库的一部分。我们都是数据库设计的新手,不能确定我们的哪个选项更好,所以我想提出这些想法,并就为什么一个比另一个更好或为什么它们可以相互比较获得最好的建议.

作为一个例子,假设我们的数据库中有如下三个表。 Car_manufacturers、Car_models 和 Car_serialNumbers。每个 Car_manufacturer 有多个 Car_model,但每个 Car_model 只有一个 Car_manufacturer。此外,每个 Car_model 有多个 Car_serialNumber,但每个 Car_serialNumber 只有一个 Car_model。这种关系创建了一个向下的树,其中 Car_manufactuere 是根,后跟 Car_model 和 Car_serialNumber。

问题是使用 mysql 在 RUby on Rails 中实现此功能的最佳方法是什么。以下是我们争论的两种方式。

我的想法是主键将是 Car_manufacturer 的 id,并将作为外键存储在 Car_model 表中。然后在 Car_manufacturer 和 Car_model 之间分别创建 has_many 到 belongs_to 关系。从 Car_model 到 Car_serialNumber 也是如此。我相信这是最好的,因为每个孩子只属于其父母之一,单个外键很简单,并且在 Ruby On Rails 中易于设置和管理关系。

我的同事的想法是我们对所有事情都使用连接表。因此, Car_manufactuere 和 Car_model 将指向一个完全独立的表,该表将保存两个键。然后,该表充当两者之间的代理。 Car_model 和 Car_serialNumber 也是如此。

因此,在我看来,这会产生不必要的额外数据。当关系可以通过将信息存储在各自的表中来完成时,为什么要创建连接表。此外,如果我对它们的理解正确的话,has_many 和 belongs_to 关系的连接表并不是它们的用途。连接表最适合 has_many 到 has_many 关系。两种方法都可以解决同一个问题,但我相信我的解决方案更简单,更简单的代码会产生更少的错误,这是我进行可靠设计的动力。

那么,对于效率和简单性来说,哪种设计更好?哪个会提供最大的好处?我在网上阅读了很多资料,但似乎没有人回答这个问题。对问题的任何输入或有用资源的链接都将不胜感激。

【问题讨论】:

  • 嗯,这是否有意义:“汽车制造商拥有并属于许多车型,车型拥有并属于许多汽车序列号​​”?如果是这样,您的同事的建议是有道理的。如果不是,那么,它没有。我相信你的方法是正确的。
  • 展开。这取决于域(汽车)。一个汽车模型可以由不同的制造商生产吗?如果是这样,那么多对多关系将是有意义的。
  • 正如您所解释的,您只需要一对多的关系,这意味着您是正确的。对于所描述的情况,同事的解决方案是矫枉过正的。
  • 那么,鉴于我的想法更适合这种关系,那么另一种方式有什么好处吗?例如长期的安全收益或更大的灵活性。如果另一种方式提供了比我更简单的方式更多的东西,那么它可能是值得的,但我想不出我的方式没有提供的任何好处。这就是我和同事吵架的原因。他说有好处,但他无法向我解释我的方式没有提供的任何独特之处。

标签: mysql ruby-on-rails database jointable


【解决方案1】:

这是一对多(您的想法)和多对多(连接表)关系之间的区别。您的数据看起来像是分层的一对多,因此在这种情况下,您的想法的实现更简单且更易于维护。

【讨论】:

    【解决方案2】:

    无法让自己阅读您的所有文字,所以我会这样做:


    Use an STI

    #app/models/car.rb
    Class Car < ActiveRecord::Base
       #fields - id, type, manufacturer_id, other, info, created_at, updated_at
       has_many :serials
       belongs_to :manufacturer
    end
    
    #app/models/cars/aventador.rb
    Class Aventador < Car
       before_create :set_details
    
       def set_details
          self.manufacturer = Manufacturer.find_by name: "Lamborghini"
          self.site = "http://www.lamborghini.com/en/models/aventador-lp-700-4/overview/"
       end
    end
    
    #app/models/serial.rb
    Class Serial < ActiveRecord::Base
       fields - id | car_id | serial | created_at | updated_at
       belongs_to :car
    end
    
    #app/models/manufacturer.rb
    Class Manufacturer < ActiveRecord::Base
       fields - id | name | founded_at | created_at | updated_at
       has_many :cars
    end
    

    这将允许您调用:

    aventadors = Aventador.all
    aventadors.each do |lambo|
       #-> lambo.serials - shows all serials for the Aventadors in your fleet!
       #-> lambo.manufacturer.name - shows the manufacturer's name
    end
    

    这样做的缺点虽然很酷,但您必须为每个汽车模型定义一个模型,并在每个模型中手动定义制造商。


    无聊的方式

    您可以按如下“无聊”的方式设置它:

    #app/models/car.rb
    Class Car < ActiveRecord::Base
       #fields - id | manufacturer_id | other | items | created_at | updated_at
       has_many :serials
       belongs_to: manufacturer
    end
    
    #app/models/serial.rb
    Class Serial < ActiveRecord::Base
       #fields - id | car_id | other | items | created_at | updated_at
       belongs_to :car
    end
    
    #app/models/manufacturers.rb
    Class Manufacturer < ActiveRecord::Base
       #fields - id | other | items | created_at | updated_at
       has_many :cars
    end
    

    【讨论】:

    • 这看起来也类似于我将如何设置我的关系和模型。很高兴确认我计划实施的内容。但有一件事是,我认为不必手动定义制造商和其他属性是不利的。我认为这是不可避免的,并且通过遵循逻辑也使代码更具可读性。
    • 我想是的!您要尝试 STI 方法吗?如果你这样做了,那就太酷了:)
    • 肯定会被提起的。这个问题主要是为了获得一些意见并在必要时打开选项。我上面给出的示例与我将使用的实际表完全不同,但它恰当地展示了我们将要处理的一些更简单的关系。
    猜你喜欢
    • 2011-11-28
    • 1970-01-01
    • 2020-11-01
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 2021-09-30
    相关资源
    最近更新 更多