迁移创建表时出现Mysql2 :: Error:表不存在

24

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

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: Table 'my_database.some_tables' doesn't exist: SHOW FULL FIELDS FROM 'some_tables'
就好像错误在说它无法创建该表,因为该表确实存在,这没有任何意义。
我尝试过的事情:
- 检查数据库.yml文件,看起来没问题。没有更改,最近也成功运行了其他迁移(虽然没有创建数据库表的迁移)。 - 运行bundle以确保所有的gems都已安装。 - 删除了schema.rb文件,使用另一个副本中的数据重新创建了数据库,并运行了rake db:schema:dump来重新创建schema.rb文件。我尝试再次运行迁移,仍然得到相同的错误。
我正在使用rails 5.1.1mysql2 0.4.6
有什么提示可以让我运行迁移吗?

看起来你已经做好了充分的准备,这可能是一个多余的问题,但是:你是否验证了是这个特定的迁移引起了问题,例如,在迁移中放置调试代码或使用环境变量来运行只有一个迁移?当你运行迁移时,日志文件中显示与此表相关的内容是什么? - Wayne Conrad
1
尝试运行 rake db:migrate:status 命令,以查看已应用于数据库的迁移。也许你会发现自己连接到了不同的模式,或者你会发现导致失败的迁移并非你认为的那个。 - Bustikiller
我的问题与使用不同的ORM有关,但留下评论以帮助其他可能遇到类似情况的人......我的迁移是ORM语法和原始SQL的混合,最初我声明表名为常量,以便根据需要重用。结果发现错误是因为我在SQL中错误地插入了表名(引号太多)。 - frederj
4个回答

34
当我试图创建一个新模型并引用在迁移到Rails 5.1之前创建的现有模型时,我遇到了类似的错误。
尽管错误消息不太清楚,但在我的情况下,问题是旧模型的主键和新模型的外键之间存在数据类型不匹配(MySQL不允许这样做)。这是因为自从Rails 5.1以来,所有主键和外键的默认数据类型都是bigint,但对于旧模型,主键类型仍然是integer。
我通过将当前模型的所有主键和外键转换为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

14

ActiveRecord migration 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

应该可以正常工作。

没错,但我认为错误应该更明确,因为我无法从信息中看到解决方案的提示。但还是谢谢! - Wellington1993

5
我想出了一个解决办法,但这仍然让我感到非常困惑。
日志文件中的错误信息并没有直接指向问题。由于某些原因,可能是 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来测试这一点,一切都运行良好)。


1
有趣。适配器可能存在错误。无论如何,感谢您记录解决方案。这可能会帮助其他遇到相同问题的人。 - Wayne Conrad
t.references :author, references: :user, foreign_key: true 这可能是你的问题,因为你将 references: :user 作为列定义的一个选项传递了进去。这可能是一个冒泡错误导致了你提到的消息。尽管我查看了 active_record 的源代码,但我没有看到任何理由它不会被忽略为一个选项。 - engineersmnky
@engineersmnky 我考虑过这个问题。我测试了完全删除那个 reference 行,只留下简单的引用行:t.references :user, foreign_key: true。不幸的是,它仍然出错了。 - Neil

0
这让我感到非常困惑,我认为我看到的原因与其他人提出的不同。在我的情况下,这是因为我的迁移文件名与其中的迁移类并不完全匹配。例如,我有一个名为20171205232654_bonus.rb的迁移文件,但在类内部声明为class CreateBonus < ActiveRecord::Migration[5.1]。一旦我将文件名更改为20171205232654_create_bonus.rb,一切都正常了。
这可能与我只创建迁移而不是完整脚手架有关,也许我做错了什么。我真的不知道我怎么会出现这种不匹配的情况。

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