【问题标题】:PRIMARY KEY issue with creating tables in Rails using rake db:migrate command with mysql使用 rake db:migrate 命令和 mysql 在 Rails 中创建表的主要问题
【发布时间】:2016-02-17 23:59:00
【问题描述】:

我的 rails 版本是 4.0.0,我的 mysql 版本是 Ver 14.14 Distrib 5.7.9,适用于 Win64 (x86_64)。根据我之前的问题Here,我正在使用旧版本的rails,因为我与mysql发生了一些冲突。 (查看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

此代码完全正确,如我正在关注的教程中所示。我还调查了其他关于堆栈溢出的similar issues here 并遵循了给出的建议。我试过monkey patch as suggested

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

我将此文件插入到我在 simple_cms 应用程序的 lib 中创建的名为 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"
  • 嘿撤消感谢您的快速响应,刚刚尝试过,我仍然得到相同的加载错误
  • 这个猴子补丁需要保存到应用程序的lib还是rails的lib中
  • 您可能很幸运将文件移动:lib/patches/abastract_mysql_adapter.rbconfig/initializers/abastract_mysql_adapter.rb - 但如果您只是在学习 rails,为什么不使用 sqlite(我也更喜欢 postgres 而不是 mysql,尤其是如果您最终托管您的heroku 上的应用程序)
  • 谢谢house9,我刚刚尝试了你的建议,我得到了完全相同的消息,但这次表明它无法在初始化程序中加载文件,即使我更改了 environment.rb 中的路径。真的卡在这里了。我回答你的问题我正在使用 mysql,因为这是我正在关注的 Lynda 教程的推荐版本。所以为了能够准确地跟随老师,我认为最好的做法是使用与他建议的完全相同的设置

标签: mysql ruby-on-rails rake primary-key dbmigrate


【解决方案1】:

我也遇到过这个问题(mysql 5.7.17 和 Rails 4.0.0)。 我通过添加file 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 问题并表示您的支持:github.com/rails/rails/issues/40967
【解决方案2】:

我通过升级mysql-adapter 解决了这个问题。

我使用 gem activerecord-jdbcmysql-adapter v1.3.14 并升级到 v1.3.21

在猴子修补解决方案之前检查您的 jdbc 适配器版本。

【讨论】:

    【解决方案3】:

    上面的解决方案没有运气(我的环境: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 中

    【讨论】:

    • 这个解决方案对我有用。其他解决方案在schema:load 上对我来说运行良好,但如果我运行rails generate migration,我会收到一个未初始化的 NATIVE_DATABASE_TYPES 常量错误。您的解决方案没有问题。谢谢。
    • 非常感谢。
    • 在 rake 测试中获取 TypeError: superclass mismatch for class ColumnDefinition。我错过了什么愚蠢的东西吗?
    【解决方案4】:

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

    MySQL 5.7 不再支持主键的 null 默认值。

    通过覆盖 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 调用行不通。甚至没有想到这一点。非常感谢:)
    • 这是正确的答案。看不出它的质量如何。
    • 如前所述,可以只使用monkeypatch class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter ,独立于实际的适配器。
    • 我在尝试数据库迁移时也面临同样的问题。请让我知道 config/initializers/abstract_mysql2_adapter.rb 的文件路径
    • 适用于 Rails 3.2。
    【解决方案5】:

    Since MySQL 5.7.3 声明为 NULL 的主键会产生错误:

    PRIMARY KEY 中的列必须不是 NULL,但如果显式声明 因为 NULL 没有产生错误。现在发生错误。例如,一个 CREATE TABLE t (i INT NULL PRIMARY KEY) 等语句被拒绝。 类似的 ALTER TABLE 语句也是如此。 (错误号 13995622, 错误 #66987、错误 #15967545、错误 #16545198)

    但是你的 Rails 版本中的create_table 仍然需要DEFAULTNULL 来代替PRIMARY KEY。我已经通过更新到较新的 rails 版本解决了这个问题。

    【讨论】:

    • 非常感谢 6. :) 由于与 railties、rails 和 mysql 的一些冲突,我实际上恢复到了旧的 rails 副本。我会看看我是否能找到一个我没有得到这里描述的冲突的版本 [stackoverflow.com/questions/31766656/…
    • 请问您使用的是什么版本的rails?这样我就可以更新到那个版本。谢谢
    猜你喜欢
    • 2011-06-08
    • 2020-01-26
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    相关资源
    最近更新 更多