add_foreign_key不创建外键

时间:2017-07-08 02:37:38

标签: ruby-on-rails sqlite ruby-on-rails-5

我使用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”,但它不会创建外键。

2 个答案:

答案 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以将外键添加到数据库。