【问题标题】:Cannot add foreign key constraint error when running rails migration运行 rails 迁移时无法添加外键约束错误
【发布时间】:2017-02-23 17:54:36
【问题描述】:

我的 MySQL 数据库中有一个 users 表。在我的 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`)

由于用户表已经存在,我很困惑为什么在权限表中创建外键失败。这可能是什么问题?

【问题讨论】:

    标签: mysql ruby-on-rails ruby-on-rails-4 activerecord


    【解决方案1】:

    我解决了这个问题。生成的权限表中users_id的列类型为int(11),用户表中id的列类型为int(11) unsigned。 TLDR:外键列的数据类型和被引用列的数据类型应该相同。

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

    我创建了一个迁移以从 users 表的 id 中删除 unsigned 属性,现在列类型已对齐,外键添加起作用了!

    【讨论】:

    • 在 Rails 5.1 中遇到了类似的问题,其中主键现在是 BigInts。我用add_column(:projects, :price_list_id, :integer, null: false) 添加了一个外键,当我尝试添加外键时,迁移被炸毁了。我需要 add_column(:projects, :price_list_id, :bigint, null: false) 作为外键,以便它们匹配。
    【解决方案2】:

    自从我们升级到 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应该会成功运行并为你添加外键。

    【讨论】:

      【解决方案3】:

      对我来说,问题在于 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 }

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          使用这个

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

          【讨论】:

            【解决方案6】:

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

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

            将 foreign_key 设置回 true --> t.references :user, foreign_key: true

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

            【讨论】:

            • 我一遍又一遍地遇到这个错误。当然,上面的一些修复工作有效,但是这个错误不断出现,我决定试一试。低,瞧,它奏效了!
            • 这是一种在本地修复它的解决方案,但在生产环境中运行它会很糟糕。
            • 本地这确实是唯一有效的解决方案。
            猜你喜欢
            • 2020-01-20
            • 1970-01-01
            • 2014-05-02
            • 1970-01-01
            • 2019-03-24
            • 2017-03-27
            • 2013-11-19
            • 2019-07-31
            相关资源
            最近更新 更多