【问题标题】:Migration to create table raises Mysql2::Error: Table doesn't exist迁移创建表引发 Mysql2::Error: Table doesn't exist
【发布时间】:2017-11-16 22:02:04
【问题描述】:

我用以下代码编写了一个迁移:

class CreateTableSomeTable < ActiveRecord::Migration[5.1]
  def change
    create_table :some_tables do |t|
      t.references :user, foreign_key: true
      t.references :author, references: :user, foreign_key: true
      t.text :summary
    end
  end
end

这是创建数据库表的基本迁移。但是:当我运行 rails db:migrate 时,一条非常奇怪的错误消息会中止迁移:

Mysql2::Error: 表 'my_database.some_tables' 不存在:SHOW FULL FIELDS FROM 'some_tables'

好像错误是说它无法创建表,因为表确实存在,这没有意义。

我看过并尝试过的事情:

  • 查看了似乎没问题的 database.yml。什么都没有改变,我最近运行了其他迁移就好了(尽管没有创建数据库表的迁移)
  • 运行 bundle 以确保所有 gem 都已安装
  • 删除了schema.rb 文件,使用另一个副本中的数据重新创建了数据库,然后我运行rake db:schema:dump 来重新创建schema.rb 文件。我尝试再次运行迁移,但仍然遇到相同的错误。

我正在使用rails 5.1.1 以及mysql2 0.4.6

关于如何让迁移运行的任何提示?

【问题讨论】:

  • 看起来你的鸭子排成一排,所以这可能是一个多余的问题,但是:你是否验证过是这个特定的迁移导致了问题,例如,通过放置调试代码在迁移中,还是使用环境变量导致只运行一个迁移?当您运行迁移时,日志文件中会显示与该表相关的内容?
  • 尝试运行rake db:migrate:status 以查看已应用于数据库的迁移。也许您发现您正在连接到不同的架构,或者您发现失败的迁移不是您认为导致失败的迁移。
  • 我的问题不同并且使用了不同的 ORM,但留下评论以帮助可能正在经历类似事情的其他人......我的迁移是 ORM 语法和原始 SQL 的混合,我有最初将表名声明为一个常量,以便根据需要在整个过程中重用。原来错误是 b/c 我在 SQL 中错误地插入了表名(引号太多)

标签: mysql ruby-on-rails ruby mysql2


【解决方案1】:

ActiveRecord 迁移 5.1 的一个大问题是,现在 id 应该是 BIGINT 而不是 INT,所以当你添加一个引用在 rails 5.1 之前创建的另一个表的列时,它期望列类型是 BIGINT,而不是只是一个INT,因此错误。 最好的解决方案是修改您的迁移并将列的类型更改为 int。

class CreateTableSomeTable < ActiveRecord::Migration[5.1]
 def change
  create_table :some_tables do |t|
   t.references :user, foreign_key: true, type: :int
   t.references :author, references: :user, foreign_key: true
   t.text :summary
  end
end

应该可以的。

【讨论】:

  • 就是这样,但我认为错误应该更明确,因为我看不到解决方案的提示阅读消息。不过谢谢!
【解决方案2】:

这让我发疯了,我想我看到的原因与其他人建议的不同。就我而言,这是因为我的迁移文件名与其中的迁移类不完全匹配。例如,我有一个名为20171205232654_bonus.rb 的迁移文件,但在类内部声明为class CreateBonus &lt; ActiveRecord::Migration[5.1]。一旦我将文件名更改为20171205232654_create_bonus.rb,一切正常。

这可能与我一直在创建迁移而不是完整的脚手架这一事实有关,也许我做错了什么。我真的不知道我是怎么结束这种不匹配的。

【讨论】:

    【解决方案3】:

    我在尝试创建一个引用了在迁移到 Rails 5.1 之前创建的现有模型的新模型时遇到了类似的错误。

    虽然错误信息不是很清楚,但在我的情况下,问题是旧模型的主键和新模型的外键之间的数据类型不匹配(MySQL不允许这样做) .之所以如此,是因为从 Rails 5.1 开始,所有主键和外键的默认数据类型都是 bigint,但对于旧模型,主键类型仍然是整数。

    我通过将当前模型的所有主键和外键转换为 bigint 解决了这个问题,因此我可以使用 Rails 的新默认值而忘记它。

    解决方法也可以为新外键指定整数类型,以便它们与旧模型的主键类型匹配。类似于以下内容:

    class CreateUserImages < ActiveRecord::Migration[5.1]
      def change
        create_table :user_images do |t|
          t.references :user, type: :integer, foreign_key: true
          t.string :url
        end
      end
    end
    

    【讨论】:

      【解决方案4】:

      我想出了一个解决方法,但这对我来说仍然很困惑。

      日志文件中的错误消息并未准确指出问题所在。出于某种原因,它可能是rails 5.1.1 或者可能是mysql2 0.4.6,但由于某种原因它不喜欢在create_table 块中使用references。很奇怪,因为它过去对我有用。

      所以我从这里更改了迁移:

      class CreateTableSomeTable < ActiveRecord::Migration[5.1]
        def change
          create_table :some_tables do |t|
            t.references :user, foreign_key: true
            t.references :author, references: :user, foreign_key: true
            t.text :summary
          end
        end
      end
      

      到这里:

      class CreateTableSomeTable < ActiveRecord::Migration[5.1]
        def change
          create_table :some_tables do |t|
            t.integer :user_id
            t.integer :author_id
            t.text :summary
          end
        end
      end
      

      它奏效了。

      这很奇怪,因为referencessqlite3 一起工作得很好(我通过生成一个虚拟应用程序对此进行了测试,使用references 列运行了一个脚手架命令,然后运行了rails db:migrate 并且一切正常)。

      【讨论】:

      • 有趣。可能是适配器中的错误。无论如何,感谢您记录分辨率。这可能会帮助遇到同样问题的其他人。
      • t.references :author, references: :user, foreign_key: true 这也可能是您的问题,因为您将references: :user 作为option 传递给列定义。这可能是导致您提到的消息的冒泡错误的情况。 (虽然查看active_record 源我看不出为什么这不会被忽略为option
      • @engineersmnky 我确实考虑过。我测试了完全删除reference 行,它只留下了简单的参考行:t.references :user, foreign_key: true。不幸的是,它仍然出错了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-10
      • 2020-03-13
      • 2021-01-15
      相关资源
      最近更新 更多