Rails 4 - 从SQLite切换到MySQL - 无法添加外键约束

3
简而言之,我开始写一个应用程序,但它不会进入生产环境,但老板喜欢它并要求我部署它。现在我必须从SQLite切换到MySQL才能将该应用程序放在生产服务器上。
我添加了gem: gem' mysql2 ',〜>0.3.20',执行了 bundle install ,并更新了database.yml:
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: 
  host: localhost

development:
  <<: *default
  database: umc2_dev

test:
  <<: *default
  database: umc2_test

production:
  <<: *default
  database: umc2
  username: umc2
  password: <%= ENV['PRODUCTION_DATABASE_PASSWORD'] %>

迁移并没有做什么复杂的操作,它们都长得像这样:
create_table :checkins do |t|
  t.string :public_ip
  t.string :private_ip
  t.string :ubermix_version
  t.string :kernel
  t.string :architecture
  t.integer :battery_capacity
  t.integer :system_free
  t.integer :home_free
  t.integer :user_free
  t.references :device, index: true, foreign_key: true
  t.references :location, index: true, foreign_key: true

  t.timestamps null: false
end

当我迁移数据库时,控制台会输出以下内容:

Mysql2::Error: Can't create table 'umc2.#sql-4e7_10' (errno: 150): \
ALTER TABLE `checkins` ADD CONSTRAINT `fk_rails_ba93b88497`

我已经为此问题苦苦思索了几个小时。我是不是漏掉了什么?我是否无意中引入了某种存储引擎的问题?MySQL 5.7.10 默认应该使用InnoDB,对吗?


1
通常情况下,150错误是由于父列和引用列之间的数据类型不匹配造成的。它们必须完全相同,并且此外,父列必须具有某种索引 - 可以是主键,如果不是,则必须建立索引。请发布SHOW CREATE TABLE checkins的MySQL输出,以及引用表的输出,这样我们可以看到哪些已经被索引。(也可能是因为在尝试创建引用表时父表尚不存在) - undefined
这是第一次运行的迁移,所以看起来我需要仔细检查和重新调整它们的顺序。我猜SQLite不会抱怨如果它们按照错误的顺序创建。 - undefined
是的 - 顺序肯定很重要。以后可能还会出现其他索引问题。 - undefined
它对生产数据库('umc2.#sql-4e7_10')提出了抱怨。将生产环境注释掉,使迁移在开发和测试中正常工作。然后专注于生产数据库。 - undefined
2个回答

1
当我运行SQLite时,我使用了资源生成器,如下所示:rails g resource checkin device:references。当你向生成器传递references类型时,它会自动将index: true, foreign_key: true添加到迁移文件中的适当行。在使用MySQL创建引用表之前,父表必须存在,但如果父表不存在,SQLite不会报错。
我不得不编写附加的迁移,将引用列添加到checkins表中。我认为你可以删除foreign_key: true部分,不影响ActiveRecord的关系,但我不确定是否这是首选解决方案。

0

在处理MySql错误:150时,必须满足以下条件。

  1. 两个表必须具有相同的引擎,例如ENGINE=InnoDB、ENGINE=MyISAM等。
  2. 两个表必须具有相同的字符集。
  3. 父表中的Primary Key列和子表中的Foreign Key列必须具有相同的数据类型。
  4. 如果父表和子表的Primary Key列和Foreign Key列定义了排序规则,则它们的排序规则必须相同。
  5. 如果Foreign Key表中已经存在数据,则Foreign Key列的值必须与Primary Key表中的Primary Key列的值匹配。
  6. 子表不能是临时表。

希望这对您有所帮助。


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