ActiveRecord :: StatementInvalid:Mysql2 :: Error:重命名

时间:2018-02-26 06:37:52

标签: ruby-on-rails migration

请跳过并直接跳到我的下面的更新4。我以更好的方式总结了这个问题。

我使用mysql(不确定我是否使用mariadb)

当我执行rails db:migrate时,我收到了这个错误:

ActiveRecord::StatementInvalid: Mysql2::Error: Error on rename of
'./my_database_name/#sql-228c_e' to './my_database_name/apples' (errno: 150): ALTER TABLE
`apples` CHANGE `gardener_id` `farmer_id` bigint(20) DEFAULT NULL

我认为因为这个文件我得到了这个错误:

# db/migrate/20171017044807_rename_gardeners_to_farmers.rb
class RenamegardenersToFarmers < ActiveRecord::Migration[5.1]
  def change
    rename_table :gardeners, :farmers
  end
end

我移动上面的rails db:migrate行并浏览了所有迁移文件并将所有rename_table字词更改为gardeners字后,我的应用正常工作且farmers正常工作。所以我认为问题确实在于重命名。

我的问题是为什么这是一个问题,我该如何解决?

更新1

抱歉,我只是重新运行迁移文件,直到#db / migrate / 20171017044807_rename_gardeners_to_farmers.rb(包括),实际上这个文件不会导致问题。它是导致问题的下一个迁移文件。

运行迁移文件db/migrate/20171017044807_rename_gardeners_to_farmers.rb之后的架构:

  create_table "apples", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.bigint "gardener_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["gardener_id"], name: "index_apples_on_gardener_id"
  end
  add_foreign_key "apples", "farmers", column: "gardener_id"

导致上述错误的下一个迁移文件:

# 20171017051611_rename_gardener_id_column_for_apples.rb
class RenameGardenerIdColumnForApples < ActiveRecord::Migration[5.1]
  def change
    rename_column :apples, :gardener_id, :farmer_id
  end
end

更新2 在听到Ngoral的回答后试图解决问题,我尝试在失败的迁移之前添加一个迁移内容:change_column :apples, :gardener_id, :references, null: false,但它不起作用。

由于&#39;不起作用,我的意思是当我尝试在添加包含我在第一条评论中显示的行的新迁移文件后运行rails db:migrate时,我发现迁移失败错误答案。

错误是这样的:

rails db:migrate
== 20171017044808 PreventGardenerIdNull: migrating ==============================
-- change_column(:apples, :gardener_id, :references, {:null=>false})
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'references NOT NULL' at line 1: ALTER TABLE `apples` CHANGE `gardener_id` `gardener_id` references NOT NULL

更新3

我认为更新2中的错误告诉我,我编写的代码存在一些错误,所以我将其更改为 change_column :apples, :gardener_id, :references, null: falsechange_column_null :replies, :author_id, false 我这样做的原因是因为我在下面的Ngoral评论(对她的答案)中看到了这个和Stack Overflow帖子:https://stackoverflow.com/a/20255645/6359753

现在,在重新运行rails db:migrate后,我得到了这个:

rails db:migrate
== 20171017044808 PreventGardenerIdNull: migrating <--------this is the migration file I added in Update 2==============================
-- change_column_null(:apples, :gardener_id, false)
   -> 0.0068s
== 20171017044808 PreventGardenerIdNull: migrated (0.0069s) =====================

== 20171017051611 RenameGardenerIdColumnForApples: migrating ===================
-- rename_column(:apples, :gardener_id, :farmer_id)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Error on rename of './my_database_name/#sql-71a_3' to './my_database_name/apples' (errno: 150): ALTER TABLE `apples` CHANGE `gardener_id` `farmer_id` bigint(20) NOT NULL

从我所看到的情况来看,问题似乎与gardener_id无关,因为迁移文件PreventGardenerIdNull成功并且RenameGardenerIdColumnForApples失败。

注意:我认为我在某种程度上违反了我的外键约束,根据这篇文章:https://stackoverflow.com/a/4061333/6359753,但我还在弄清楚到底出了什么问题。 注意:mysql -u root表明我的mariaDB服务器版本为:Server version: 5.5.56-MariaDB MariaDB Server

更新4: 我想在经过所有调查和答案后,我现在可以更好地总结一下这个问题:

1)忽略上面这个问题中的所有内容

2)mysql -u root表明我的mariaDB服务器版本是:Server version: 5.5.56-MariaDB MariaDB Server

3)下面按时间顺序显示:

[时间= 1]架构1:

  create_table "gardeners", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "apples", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.bigint "gardener_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["gardener_id"], name: "index_apples_on_gardener_id"
  end
  add_foreign_key "apples", "gardeners"

[Time = 2]使用代码运行迁移:

rename_table :gardeners, :farmers

[时间= 3]架构2:

  create_table "farmers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "apples", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.bigint "gardener_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["gardener_id"], name: "index_apples_on_gardener_id"
  end
  add_foreign_key "apples", "farmers", column: "gardener_id"

[Time = 4]使用代码运行迁移:

rename_column :apples, :gardener_id, :farmer_id

收到错误:

== 20171017051611 RenameGardenerIdColumnForApples: migrating ===================
-- rename_column(:apples, :gardener_id, :farmer_id)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Error on rename of './my_database_name/#sql-71a_3' to './my_database_name/apples' (errno: 150): ALTER TABLE `apples` CHANGE `gardener_id` `farmer_id` bigint(20) NOT NULL

[时间= 5](从未发生)我想要更改为的架构:

  create_table "farmers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "apples", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.bigint "gardener_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["gardener_id"], name: "index_apples_on_gardener_id"
  end
  add_foreign_key "apples", "gardeners"

我有两个问题:

1)为什么我在[time = 4]

失败

2)我应该在[time = 4]使用什么迁移代码,或者我应该在[time = 2]使用什么迁移代码来防止所有这些问题?

非常感谢!

2 个答案:

答案 0 :(得分:0)

this问题涵盖了您的问题。

问题是由迁移调用的DEFAULT NULL语句引起的,可以在SQL转储中清楚地看到。对于您使用的InnoDB,此类声明不正确(从架构中可以看出)。

所以,我猜你不希望gardener_id为零。在这种情况下,创建为null: false设置gardener_id的迁移应该有所帮助。

因此,您首先创建一个不允许gardener_id为nil的迁移,然后将您的迁移现在失败。

============ 更新后回答您的问题: 您的迁移在步骤4失败,原因如上所述:gardener_id的默认值为空,而您的数据库不允许这样做。

在重命名之前,您应该使用命令change_column_null :apples, :gardener_id, false运行迁移。更改默认null后,运行重命名迁移。 您运行的命令语法无效,它清楚地告诉您。

答案 1 :(得分:0)

我正在使用MariaDB 5.5.64版本。我改为使用MariaDB 10.4版,此迁移问题就消失了。