我使用Rails 5.1和SQLite。以下迁移未按预期工作。
class AddJobTitleForeignKeyToTimeOffTypes < ActiveRecord::Migration[5.1]
def change
add_column :time_off_types, :job_title_id, :integer
add_foreign_key :time_off_types, :job_title, :column => :job_title_id
end
end
它在表“time_off_types”中创建列“job_title_id”,但它不会创建外键。
答案 0 :(得分:2)
ActiveRecord的add_foreign_key
方法在表创建之外使用,因此使用ALTER TABLE ... ADD CONSTRAINT ...
。
SQLite的ALTER TABLE
不支持添加约束(任何类型)。 (值得回顾一下,因为SQLite中的ALTER TABLE
可能比您预期的要受限制。例如,SQLite <3.25.0
也不能重命名列。)
但是,SQLite CREATE TABLE
确实支持外键约束,并且ActiveRecord迁移create_table
#references
方法可以创建它们:
def change
create_table :pets do
t.references :owner, foreign_key: true
...
end
end
《 Rails迁移指南》未提及这种区别。
那么这是如何工作的?
ActiveRecord数据库适配器具有两种方法:supports_foreign_keys?
和supports_foreign_keys_in_create?
,默认情况下均为false
(请参见Rails API文档)。
add_foreign_key
returns immediately,除非supports_foreign_keys?
是true
,但是对于SQLite,它是false
,因此对于add_foreign_key
来说是结尾。 / p>
另一方面,为SQLite> = 3.6.19
使用supports_foreign_keys_in_create?
is true
,这允许#references
方法使用CREATE TABLE ...
创建外键。
(我已经链接到Rails 5.1代码,因为这是您在提问时所使用的,但是从今天的Rails 5.2.1开始,这一切都是正确的。)
答案 1 :(得分:0)
我目前认为这是因为SQLite不支持rails执行的某些SQL以将外键添加到数据库。