如何在rails中实现复合主键

Posted

技术标签:

【中文标题】如何在rails中实现复合主键【英文标题】:How to implement composite primary keys in rails 【发布时间】:2017-06-12 19:33:28 【问题描述】:

我有一个看起来像这样的User 模型:

class User < ApplicationRecord
  belongs_to :organization
  belongs_to :department
end

数据库中的users 表有两个外键organization_iddepartment_id。如何使这两列成为复合主键?到目前为止,我在网上看到了两种方法:

选项 1

使用composite_primary_keys gem

选项 2

使用以下方法为两列中的每一列添加索引:

add_index :users, [:organization_id, :department_id], unique: true

我的问题

users 表中唯一标识行的最佳方法是什么,其中行必须具有department_idorganization_id 才能被唯一标识?索引两列和简单地使每列成为表的主键有什么区别?

谢谢!

【问题讨论】:

首先,为什么要使用复合主键而不是遵循 Rails 约定,并且只具有与组织和部门的id 列和belongs_to 关联?复合主键对应用程序的许多其他部分有影响:Rails 链接助手可能无法与复合键一起使用,查找器的工作方式不同,外键更难使用...... 选项 2 是最好的选择。选项 1 是您在别无选择时所做的,例如您背负着无法更改的旧数据库。 【参考方案1】:

添加索引。

在 Rails 中,如果你有 id 作为主键,一切都会更好。

可能你可以破坏系统......但最好不要这样做,除非你真的知道你在做什么 - 如果你问索引和键之间的区别是什么,那么您就不会...这很酷顺便说一句,您不需要知道这一点就可以很好地使用Rails...但是如果您要去的话,它真的很有帮助改变一些根本性的东西。因为使用 id 以外的任何东西作为主键更难。事情更糟。您将不得不在不了解它们为什么会损坏以及为什么首先需要它们的情况下对其进行修复...

id 作为主键并有一个约束来确保你有一个唯一的organisation_id+department_id...

注意:我假设您不知道索引/主键之间的区别 - 这个假设可能不成立,但这是您提出问题的方式的产物......如果是这样,我很抱歉。 :) 在这种情况下...不同之处在于,如果您只使用它所期望的,Rails 就会为您提供各种美妙的魔法......如果您不使用它,它就是一个 PITA。

否则... 主键是唯一标识信息的位。您可能会认为 org_id/dept_id 永远不会改变...但您会惊讶于现实世界中的数据在现实生活中的变化频率...以及更新整个数据库的关系价值会带来多大的痛苦确实...

唯一索引 (OTOH) 可以按照您想要的方式很好地限制数据...如果有人决定现在必须将 42 部门设为 23 部门,则无需更新内容。 此外,索引可让您通过该列对查找数据,这比对整个数据库进行行扫描要快得多。

【讨论】:

好的,是的,我只是在关注数据库的东西..但我知道当你偏离它的约定时,rails 会变得很糟糕。那我就用索引方法吧,谢谢! 另外,你可能会发现现实决定了这种关系应该很快就会成为 m2m ...... 很好的答案 - 我实际上正在为我正在从事的项目决定这件事。不确定是否有任何缺点,但现在会采取这条路线。谢谢。 我想知道部门编号与 ids 有什么关系... 列出分区表呢?不可能通过 ID 做所有事情。

以上是关于如何在rails中实现复合主键的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate:insertable = false,updatable = false 属于涉及外键的复合主键星座中的哪里?

如何在 SQL 中定义复合主键?

如何在 Room 持久库中使用复合主键时使主键自动递增?

Hibernate:复合主键 - 外键:如何在两个表之间映射各个字段

如何在表上创建复合主键 [重复]

Laravel中定义复合主键