Rails中reference与foreign key的区别

对add_reference, remove_reference, add_foreign_key, remove_foreign_key这四个有点拎不清,查了官方的API,记录下。

部分实例取自官网。

add_reference VS add_foreign_key

  • add_reference(table_name, ref_name, **options)

    用来给表添加一个参考列,使用时,options可以有如下的设置:

    :type
    参考列的类型. 默认是 :bigint.
    
    :index
    添加一个键. 默认是 true.
    
    :foreign_key
    添加一个合适的外键约束. 默认是 false.
    
    :polymorphic
    多态关联,也就是是否需要添加额外的_type. 默认是 false, 即不添加, 设置为true时,则添加上_type
    
    :null
    该列是否允许为 nulls. 默认是 true.
    

    以articles,authors为例,这里我们主要看添加外键:

    add_reference :articles, :author, foreign_key: true
    

    上面的这种用法,使用add_foreign_key可以这样写:

    add_foreign_key :articles, :authors
    

    默认添加的列名为author_id。

    或者指定列名:

    add_foreign_key :articles, :authors, column: :custom_author_id, primary_key: 'id'
    
  • add_foreign_key(from_table, to_table, options = {})

    用来给表添加一个外键,使用时,options可以有如下的设置:

    :column
    外键列的名字. 默认是to_table的单数形式 + "_id"
    
    :primary_key
    to_table的主键. 默认是 id.
    
    :name
    约束名或者说是外键的名称 默认是 fk_rails_<identifier> 样式,identifier是一个根据from_table和column来生成的总长为10的字符串,比如fk_rails_e74ce85cbc.
    
    :on_delete
    发生删除时的行为,可设置为nullify,cascade, restrict
    
    :on_update
    发生更新时的行为,同delete
    
    :validate
    只用于Postgres, 指定是否应该验证约束. 默认是 true.
    

    add_foreign_key还可以指定to_table主表delete或者update时,from_table从表的行为约束。

    nullify:删除/更新主表时,自动更新从表值为NULL。删除/更新从表,主表不变

    cascade:删除/更新主表时,自动删除/更新从表。删除/更新从表,主表不变

    restrict:从表记录不存在时,主表才可以删除/更新。删除/更新从表,主表不变

  • 两者的区别

    add_foreign_key是用来添加外键的method,但是add_reference却不一定添加的就是外键,如果在options中,添加了foreign_key: true, 那么其效果就同add_foreign_key的基本用法。

remove_reference VS remove_foreign_key

  • remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)

    顾名思义,移除reference。

    移除单个reference,同时移除index:

    remove_reference(:products, :user, index: true)
    

    移除设置为多态关联的reference:

    remove_reference(:products, :supplier, polymorphic: true)
    

    移除外键:

    remove_reference(:products, :user, index: true, foreign_key: true)
    
  • remove_foreign_key(from_table, options_or_to_table = {})

    移除外键约束。

    移除一个外键, 这里移除了accounts的branch_id 这个外键:

    remove_foreign_key :accounts, :branches
    

    指定移除的外键列:

    remove_foreign_key :accounts, column: :owner_id
    

    指定移除的外键名称,这里移除了accounts表中名为special_fk_name的外键。「前面add_foreign_key中,可以通过name来设定添加的外键名称。」

    remove_foreign_key :accounts, name: :special_fk_name
    
  • 两者的区别

    基本同添加外键一样,remove_reference当指定了foreign_key: true 时,等同与remove_foreign_key。比如下面这个例子:

    remove_reference :groups, :order, foreign_key: true
    ## 等同于下面这两种写法
    remove_foreign_key :groups, :orders
    remove_foreign_key :groups, column: :order_id
    

参考

add_reference

add foreign key

remove_reference

remove foreign key