index: true 与foreign_key: true (Rails)

问题描述 投票:0回答:2

按照指南,我运行了以下命令:

rails g migration CreateSnippetsUsers snippet:belongs_to user:belongs_to

这创建了以下迁移:

class CreateSnippetsUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :snippets_users do |t|
      t.belongs_to :snippet, foreign_key: true
      t.belongs_to :user, foreign_key: true
    end
  end
end

过去我也见过同样的事情,但用的是

index: true
而不是
foreign_key: true
。两者有什么区别?

ruby-on-rails foreign-keys ruby-on-rails-5 rails-activerecord rails-migrations
2个回答
34
投票

索引外键外键约束是数据库中严格相关的概念,经常被混淆或误解。

参考文献
当你声明一个 reference 时,你只是说要包含一个列,其值应该与另一个表的值匹配(并且在 Rails 中,你还可以获得一些有用的方法来浏览关联的模型)。在示例中:

create_table :appointments do |t|
  t.references :student
end

appointments
表将有一个名为
student_id
的列,其值应位于学生 ID 值池中。

索引
由于当您添加引用时,您可能会经常使用该列,因此您可以(并且可能应该!)还告诉您数据库使用引用列来提高查找速度。您可以使用选项

index: true
来完成此操作(顺便说一下,自 Rails 5 以来,这是
reference
方法中的默认选项)。索引几乎没有缺点,主要是内存消耗较大。

外键限制
从目前来看,

reference column
foreign column
是同义词。但是您还记得我说过参考列的值应该与另一个表的值匹配吗?如果您只是声明引用,则您有责任确保引用的表上存在匹配的行,否则有人最终会执行无意义的操作,例如为不存在的学生创建约会。这是数据库完整性的一个例子,幸运的是,有一些机制可以授予更强的完整性级别。这些机制称为“数据库约束”。选项foreign_key: true所做的正是在引用列上添加这种约束,拒绝任何外键值不在引用表中的条目。
数据库完整性是一项复杂的任务,随着数据库的复杂性而变得越来越困难。您可能还应该添加其他类型的约束,例如在班级中使用关键字 

dependent: :destroy

,以确保当您删除学生时,其所有现有约会也会被销毁。

与往常一样,这里有一个 RTFM 链接:

https://guides.rubyonrails.org/association_basics.html


19
投票
index: true

时,它会向该列添加数据库索引。例如我正在创建一个表:


create_table :appointments do |t| t.references :student, index: true end

它将在 
student_id

表中创建

appointments
列。

外键有不同的用例,它是表之间的关系。它允许我们在一个表中声明与另一表中的索引相关的索引,并且还设置一些约束。数据库强制执行这种关系的规则以维护引用完整性。例如我们有两个表

profiles

educations
,并且一个配置文件可能有很多教育背景。

create_table :educations do |t| t.belongs_to :profile, index: true, foreign_key: true end

现在我们在 
profile_id

表中有

educations
列,它是
profiles
表的外键。它会阻止记录输入到
educations
表中,除非它包含
profile_id
表中存在的
profiles
值。因此将保持引用完整性。
    

© www.soinside.com 2019 - 2024. All rights reserved.