使外键也成为 Rails 迁移中的主键

Make a foreign key also a primary key in a Rails migration

编辑:

从 Rails 的角度来看,我希望列既是主键又是外键。也就是说使用references方法的外键。我想做类似的事情:

def change
  create_table :VipPerson, id: false do |t|
    t.primary_key :person_id
    t.references :person, :id, column: :person_id

    t.timestamps
  end
end

我想要一个自定义主键,Rails 模型也使用它来指向 Person 模型(见下文)。这实际上与 sql 数据库使用的外键无关(Rails 直到 Rails 4.2 才支持创建真正的外键,正如所指出的由 Demi Magus 创作)。

-

我想在我的 Rails 项目中实现多重 Table Interitance (MTI),因此像您通常在关系数据库中那样实现继承:

table: Person
-------------
(PK) ID
Name
...

table: VipPerson (specalization of Person)
----------------
(PK) (FK) Person_ID
VIP-Status
...

因此,为此我需要编写一个迁移,将属性(此处 Person_ID)同时声明为(自定义)主键和外键。我看不出如何使用 Rails' 迁移 DSP 的方法来做到这一点。

我不想使用 Rails' 多态关联,因为我想保证数据库中的数据完整性。我知道我还需要自定义 Rails 模型,但我们先不谈这个话题。主要问题是如何编写使 PK 也成为 FK(反之亦然)的迁移。

外键关系只适用于rails的最新版本,如您在release notes中看到的那样是4.2,您可以这样使用它

创建一个简单的外键

add_foreign_key :articles, :authors

生成:

ALTER TABLE "articles" ADD CONSTRAINT articles_author_id_fk FOREIGN KEY ("author_id") REFERENCES "authors" ("id")

您还应该知道 add_foreign_key 只会生成外键约束,而不是像 activerecord add_column 那样的列

add_column :articles, :author_id, :integer

将生成:

ALTER TABLE "articles" ADD COLUMN author_id INT(11);

您可以找到更多信息here

此外,如果您不只是寻找 rails 的边缘,那么您会发现这个 gem 很有用,它允许您做您正在寻找的 composite_primary_keys ], 唯一需要注意的是,您必须使用与您的 rails 版本兼容的版本。

希望对您有所帮助:D

解决方案是在模型中手动设置主键和外键,而不是在迁移中摆弄(注意你必须告诉 Rails 不要通过传递 "id: false" 来创建默认列 ID选项):

迁移:

def change
  create_table :VipPerson, id: false do |t|
    t.primary_key :person_id  # Normal integer PK, shouldn't auto-increment
    t.integer :vip_status
    ..... etc.
  end
end

模型中:

class VipPerson < ActiveRecord::Base
  self.primary_key = "person_id"
  belongs_to :person, foreign_key: "person_id"
end

只需手动指向模型中的同一列。然后,在数据库层,您可以使用真正的外键约束来额外增强主键(参见 Demi Magus 的回答)。