使用rake db:migrate命令在Rails中创建mysql表时出现主键问题

24
我的Rails版本是4.0.0,MySQL版本是Ver 14.14 Distrib 5.7.9,适用于Win64(x86_64)。由于我之前的问题(在这里)中遇到了一些与MySQL冲突的情况,因此我正在使用较旧版本的Rails。(请检查Kalelc的批准答案以进行解决)。
在运行时,
rake db:migrate 

我收到了以下错误信息
==  CreateUsers: migrating ====================================================
-- create_table(:users)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead: CREATE TABLE `users` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `first_name` varchar(25), `last_name` varchar(50), `email` varchar(255) DEFAULT '' NOT NULL, `password` varchar(40), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDBC:/Users/Lizanne/Documents/Code/Sites/simple_cms/db/migrate/20151116154434_create_users.rb:3:in `up'
C:in `migrate'
ActiveRecord::StatementInvalid: Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead: CREATE TABLE `users` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `first_name` varchar(25), `last_name` varchar(50), `email` varchar(255) DEFAULT '' NOT NULL, `password` varchar(40), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
C:/Users/Lizanne/Documents/Code/Sites/simple_cms/db/migrate/20151116154434_create_users.rb:3:in `up'
C:in `migrate'
Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead
C:/Users/Lizanne/Documents/Code/Sites/simple_cms/db/migrate/20151116154434_create_users.rb:3:in `up'
C:in `migrate'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

我在我的代码中没有将任何值设置为NULL,以下是代码:

Class CreateUsers < ActiveRecord::Migration

  def up
    create_table :users do |t| 
      t.column "first_name", :string, :limit => 25 
      t.string "last_name", :limit => 50
      t.string "email", :default => "", :null => false 
      t.string "password", :limit => 40
      t.timestamps
    end
  end

  def down
    drop_table :users
  end
end

这段代码与我正在跟随的教程完全相同。我还查看了其他类似问题在stack overflow上,并遵循了给出的建议。我已尝试使用monkey patch 如建议所示

# lib/patches/abastract_mysql_adapter.rb
class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end

我把这个文件插入到我创建的一个名为patches的文件夹中,该文件夹位于我的simple_cms应用程序的lib目录下。我按照同一monkey patch建议将文件保存为"abstract_mysql_adapter.rb"。 我已经使用以下内容更新了simple_cms应用程序的environment.rb

require File.expand_path('../../lib/patches/abstract_mysql_adapter.rb', __FILE__)

如果我接下来运行“rake db:migrate”命令。
rake aborted!
LoadError: cannot load such file -- C:/Users/Lizanne/Documents/Code/Sites/simple_cms/lib/patches/abstract_mysql_adapter.rb
C:/Users/Lizanne/Documents/Code/Sites/simple_cms/config/environment.rb:3:in `<top (required)>'
Tasks: TOP => db:migrate => environment
(See full trace by running task with --trace)

C:/Users/Lizanne/Documents/Code/Sites/simple_cms/lib/patches/abstract_mysql_adapter.rb是猴子补丁的路径。我把补丁放错了吗?我在这个问题上纠结了很久,不知道自己做错了什么。如果对一些人来说这很明显,那我向你们道歉,因为我已经很久没有写代码了,现在无法理解这个问题。非常感谢您的帮助 :)


尝试将你的猴子补丁编辑为"int(11) auto_increment PRIMARY KEY NOT NULL" - Undo
嘿Undo,感谢您的快速回复,我刚试了一下,仍然遇到了相同的加载错误。 - Aerosewall1
你可能会有运气将文件 lib/patches/abastract_mysql_adapter.rb 移动到 config/initializers/abastract_mysql_adapter.rb - 但如果你只是在学习Rails,为什么不使用sqlite呢?(我也更喜欢Postgres而不是MySQL,特别是如果你最终要在Heroku上托管你的应用程序) - house9
谢谢house9,我刚刚尝试了你的建议,但是我收到了完全相同的消息,但这次它说无法在初始化程序中加载文件,即使我已经在environment.rb中更改了路径。真的卡在这里了。回答你的问题,我正在使用mysql,因为这是我正在遵循的Lynda教程推荐的版本。所以为了能够完全跟随老师的步骤,我认为最好使用他建议的完全相同的设置。 - Aerosewall1
刚刚尝试了 bundle exec rake db:migrate,但还是不行,出现了同样的错误。 - Aerosewall1
显示剩余5条评论
5个回答

75

我最近也遇到了相同的问题。

MySQL 5.7不再支持将空值作为主键的默认值。

通过在MySql中覆盖主键的本地默认值,您可以解决您的问题。

在config / initializers / abstract_mysql_adapter.rb中:

class ActiveRecord::ConnectionAdapters::MysqlAdapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end

对于mysql2来说,它应该是config/initializers/abstract_mysql2_adapter.rb:

class ActiveRecord::ConnectionAdapters::Mysql2Adapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end

谢谢,这很有道理。a) 我没有注意到地址的类型,你能发现这点真不错。我也在使用mysql2,所以我猜lib/patches/abastract_mysql_adapter.rb的调用可能行不通。我甚至没有想到过这一点。非常感谢 :) - Aerosewall1
7
这是正确的答案。不明白为什么被评为低质量。 - Subimage
当我尝试进行数据库迁移时,我也遇到了同样的问题。请告诉我config/initializers/abstract_mysql2_adapter.rb文件的路径。 - George Varghese
适用于Rails 3.2。 - Joshua Pinter
注意,这在Rails 5.1上已不再有效。好消息是Rails 5.1将主键的默认列类型设置为“bigint”,但坏消息是它是“带符号的”而不是“无符号的”。而且它不像你在这里做的那样容易覆盖默认值。如果您想要“无符号的bigint”成为默认值,请查看此Github问题并表示支持:https://github.com/rails/rails/issues/40967 - Joshua Pinter
显示剩余2条评论

13

之前尝试的解决方案都没有用(我的环境:Rails 3.0.20,MySQL 5.7.13,Ruby 1.9.3p551)。我通过重写 ActiveRecord::ConnectionAdapters::ColumnDefinition 类绕过了这个问题。请参见下文:

class ActiveRecord::ConnectionAdapters::ColumnDefinition
  def sql_type
    type.to_sym == :primary_key ? 'int(11) auto_increment PRIMARY KEY' : base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
  end 
end

将它存储在 config/initializers/column_definition.rb 中


1
这个解决方案对我很有效。其他的解决方案在 schema:load 上运行良好,但如果我运行 rails generate migration,就会出现 NATIVE_DATABASE_TYPES 的未初始化常量错误。你的解决方案没有问题。谢谢。 - brightball
1
非常感谢您。 - Astik Anand
在运行rake测试时,出现了TypeError: superclass mismatch for class ColumnDefinition错误。我是不是漏掉了什么愚蠢的东西? - B. Shea

4

我也遇到了这个问题(mysql 5.7.17和Rails 4.0.0)。 我通过添加一个文件config/initializers/mysql2_adapter.rb来解决它。

require 'active_record/connection_adapters/mysql2_adapter'
class ActiveRecord::ConnectionAdapters::Mysql2Adapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end

然后,在我的environment.rb文件中:
require File.expand_path('../initializers/mysql2_adapter', __FILE__)

注意,这在Rails 5.1上不再起作用。好消息是Rails 5.1将主键的默认列类型设置为bigint,但坏消息是它是signed而不是unsigned。而且它不像你在这里做的那样容易覆盖默认值。如果您想要unsigned bigint成为默认值,请查看此Github问题并表示支持:https://github.com/rails/rails/issues/40967 - Joshua Pinter

2
自MySQL 5.7.3版本起,声明为NULL的主键会产生错误:
在PRIMARY KEY中的列必须为NOT NULL,但如果明确声明为NULL则不会出现错误。现在会出现错误。例如,类似于CREATE TABLE t(i INT NULL PRIMARY KEY)的语句将被拒绝。类似的ALTER TABLE语句也是如此。(Bug#13995622,Bug#66987,Bug#15967545,Bug#16545198)
但是,在您的Rails版本中,create_table仍需要DEFAULT或NULL作为PRIMARY KEY。我通过升级到更高版本的Rails解决了这个问题。

非常感谢,高兴6。:) 实际上,我因为与railties、rails和mysql冲突而回退到了较旧的rails版本。我将看看能否找到一个版本,在该版本下我不会遇到如此描述的这种冲突 [http://stackoverflow.com/questions/31766656/nameerror-on-executing-rails-s]。 - Aerosewall1
1
请问您正在使用哪个版本的Rails?这样我就可以更新到相应的版本了。谢谢。 - Aerosewall1

0

我通过升级mysql-adapter解决了我正在使用JRUBY开发的Rails应用程序中的这个问题。

我之前使用的是gem activerecord-jdbcmysql-adapter v1.3.14,现在已经升级到v1.3.21。

在打补丁之前,请检查您的jdbc适配器版本。


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