在Rails中,add_foreign_key和add_reference有什么区别?

24

"add_foreign_key""add_reference"方法在Rails中有什么区别?

根据Rails官方指南,我理解的是它们都用于在两个表之间创建外键约束。

3个回答

26

add_foreign_key - 添加一个新的外键。 from_table 是具有键列的表,to_table 包含参考主键。

add_reference - 旨在为同时创建列、索引和外键提供快捷方式。

什么是外键 - 外键是表中的一个或一组字段,用于唯一标识另一张表中的行。


4
除此之外,外键是维护引用完整性的一种方式。如果您拥有一个依赖于位置的用户,您希望在用户依赖该位置时防止删除该位置。外键就是实现这一点的方法。 - mpowered
看起来(至少在Rails 7中),add_referenceforeign_key选项默认为false,传递true以添加。 https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference - pixelearth

19

(注意:本答案基于Rails 6.0版本。)

简单来说,add_reference (Ref) 是一种缩写形式,相当于同时使用 add_columnadd_indexadd_foreign_key (Ref),但默认不添加数据库级别的外键。因此,当你想要实现比较简单的功能或者(相反地?)多态引用时,add_reference 很方便。如果不是这种情况,可以使用 add_foreign_key,也许需要结合明确的 add_index 使用。

举个简单的例子,我认为以下两者是等价的:

add_reference   :articles, :author, foreign_key: true

add_column      :articles, :author_id, :bigint, null: true
add_foreign_key :articles, :authors
add_index       :articles, :author_id

以下是更详细的区别:

  1. add_reference 的第二个参数是引用(没有 _id 的列名,通常是单数形式),而 add_foreign_key 的第二个参数是表名(通常是复数形式)。
  2. add_reference 中,
    1. 默认情况下不会创建 DB 级别的外键,除非指定了非空的 foreign_key 选项。
    2. index: true 是默认值,在 add_foreign_key 中索引是无关紧要的。
    3. null: true 是默认值(允许该列为空),在 add_foreign_key 中无关紧要。
  3. polymorphic: true 仅在 Rails 的 add_reference 中可用(它将在一个操作中创建两个列; 参见 Ref)。
  4. 虽然 add_reference 可以接受更广泛的选项范围,但两者接受选项的格式完全不同。

两个实际使用案例

对于禁止为空的 has_one 关联:

add_reference :products, :merchant, null: false, index: {unique: true}, foreign_key: {on_delete: :cascade}

当一个表有两个外键列指向相同的表时:

add_foreign_key :products, :merchants, column: :seller_id
add_foreign_key :products, :merchants, column: :buyer_id
add_index :products, [:seller_id, :buyer_id], unique: true, name: 'index_my_name_shorter_than_64chars'

4
非常感谢您的回答。我花了很长时间寻找能够涵盖所有这些事情的答案。 - seeker

0

相比于add_foreign_key,add_reference有一定的限制。

我很好奇是否有一种方法可以使用add_reference来实现完全相同的操作。据我所知,标准的外键到主键/参考键映射不能通过add_reference进行分歧。

迁移片段

add_foreign_key :foos, :bars, column: :foo_key, primary_key: :foo_key, type: :string 
add_index :foos

使用情况是当尝试以非标准方式将外键映射到主键时。例如,使用一张包含STI的表来保存多个引用


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