使外键也成为 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 的回答)。
编辑:
从 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 的回答)。