Rails 4 - 从 SQLite 切换到 MySQL - 无法添加外键约束
Rails 4 - Switching from SQLite to MySQL - Cannot add foreign key constraint
长话短说,我开始编写一个无法投入生产的应用程序,但我的老板喜欢它并让我部署它。现在我必须从 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 吧?
I例MySql error: 150
,必须满足以下条件。
- 这两个 table 必须具有相同的引擎,即 ENGINE=InnoDB、ENGINE=MyISAM 等
- 两个 table 必须具有相同的字符集。
- parent table 中的
Primary Key
列和 child table 中的 Foreign Key
列必须是相同的数据类型。
parent table 中的 Primary Key
列和 child table 中的 Foreign Key
列,如果他们有一个定义的排序规则类型,必须有相同的排序规则
类型。
- 如果
Foreign Key
table 中已有数据,Foreign Key
列值必须与 Primary Key
table Primary Key
列。
- 并且childtable不能是临时的table。
希望这会有所帮助。
当我是 运行 SQLite 时,我使用这样的资源生成器:rails g resource checkin device:references
。当您将 references
类型传递给生成器时,它会自动将 index: true, foreign_key: true
附加到迁移文件中的适当行。父 table 必须存在才能使用 MySQL 创建引用 table,但如果父 table 首先不存在,SQLite 不会抱怨。
我不得不编写额外的迁移,将引用列添加到签入 table。我认为您可以删除 foreign_key: true
位而不影响 ActiveRecord 关系,但我不确定这是否是首选解决方案。
长话短说,我开始编写一个无法投入生产的应用程序,但我的老板喜欢它并让我部署它。现在我必须从 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 吧?
I例MySql error: 150
,必须满足以下条件。
- 这两个 table 必须具有相同的引擎,即 ENGINE=InnoDB、ENGINE=MyISAM 等
- 两个 table 必须具有相同的字符集。
- parent table 中的
Primary Key
列和 child table 中的Foreign Key
列必须是相同的数据类型。
parent table 中的 Primary Key
列和 child table 中的Foreign Key
列,如果他们有一个定义的排序规则类型,必须有相同的排序规则 类型。- 如果
Foreign Key
table 中已有数据,Foreign Key
列值必须与Primary Key
tablePrimary Key
列。 - 并且childtable不能是临时的table。
希望这会有所帮助。
当我是 运行 SQLite 时,我使用这样的资源生成器:rails g resource checkin device:references
。当您将 references
类型传递给生成器时,它会自动将 index: true, foreign_key: true
附加到迁移文件中的适当行。父 table 必须存在才能使用 MySQL 创建引用 table,但如果父 table 首先不存在,SQLite 不会抱怨。
我不得不编写额外的迁移,将引用列添加到签入 table。我认为您可以删除 foreign_key: true
位而不影响 ActiveRecord 关系,但我不确定这是否是首选解决方案。