运行Rails迁移时出现无法添加外键约束错误

20

我在MySQL数据库中有一个用户表。在我的Rails 4应用程序中,我创建了一个名为Permission的模型,如下所示:

rails g model Permission user:references privilege:references

当我运行创建权限表的迁移时,表确实在数据库中创建了,但我收到了以下错误:

== 20170223171936 CreatePermissions: migrating ================================
-- create_table(:permissions)
rake aborted!
StandardError: An error has occurred:

Mysql2::Error: Cannot add foreign key constraint: ALTER TABLE `permissions` ADD CONSTRAINT `fk_rails_d9cfa3c257`
FOREIGN KEY (`user_id`)
  REFERENCES `users` (`id`)

由于用户表已经存在,我不明白为什么在权限表中创建外键会失败。可能出了什么问题呢?

7个回答

16

我已经修复了这个问题。生成的权限表中users_id列的数据类型为int(11),而用户表中id列的数据类型为int(11) unsigned。简而言之:外键列和被引用列的数据类型应该相同。

您可以通过运行show full columns from <table_name>来查看列类型。您还可以通过运行show engine innodb status来查看添加外键失败的确切原因。

我创建了一个迁移来删除用户表中id列的无符号属性,现在列类型对齐后,成功添加了外键!


4
在Rails 5.1中,我遇到了类似的问题,其中主键现在是BigInts。 我添加了一个带有add_column(:projects, :price_list_id, :integer, null: false)的外键,但当我尝试添加外键时,迁移失败了。我需要使用add_column(:projects, :price_list_id, :bigint, null: false)来添加外键,以便它们匹配。 - Yardboy

12

自从我们升级到Rails 5.2以来,我处理这个问题的方式是:

我先创建迁移文件 rails g model Example user:references

然后,在运行迁移之前,我打开迁移文件并将 t.references :user, foreign_key: true 编辑为 t.references :user, foreign_key: true, type: :integer

之后运行 rake db:migrate 就可以成功运行并添加外键。


2
对我来说问题在于Rails查找的是错误的表格,用于我正在创建的关系。我正在创建一个自引用表,并在我的迁移中运行以下内容: add_reference :categories, :linked_category, foreign_key: true 我想要列名为linked_category_id。
发生的情况是Rails正在查找一个名为linked_categories的表格,但该表格不存在:
FOREIGN KEY (`linked_category_id`)
  REFERENCES `linked_categories` (`id`)

解决方案是设置外键应该引用哪个表: add_reference :categories, :linked_category, foreign_key: { to_table: :categories }

0

使用这个

rails g model Permission user:integer:index privilege:integer:index

0

我经常遇到这个问题,因为在外键所针对的列上缺少索引。


0

对于在向包含数据的现有表添加索引时遇到此错误的人:

  1. 备份表数据(即创建转储文件),以便在需要时能够撤消所有操作

  2. TRUNCATE 表(完全清空和重置)

  3. 再次运行迁移(表为空)。

(当迁移想要为表添加索引并发现表中有记录时,它将想要为这些记录添加索引数据。但是它无法这样做,因为没有提供数据。因此,当没有记录存在时,它将不会尝试执行此操作 - 因此不会出现错误。)


-3

将外键设置为false --> t.references :user, foreign_key: false

重置数据库 --> rails db:migrate:reset,

将外键重新设置为true --> t.references :user, foreign_key: true

然后迁移数据库 --> rails db:migrate


我一遍又一遍地遇到这个错误。当然,上面的一些修复方法确实起作用了,但是由于这个错误不断出现,我决定尝试这个方法。结果居然奏效了! - OBCENEIKON
这是一个本地修复的解决方案,但在生产环境中运行会遇到很多问题。 - awilkening
本地化确实是目前唯一可行的解决方案。 - Nikolai Manek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接