SQLite3 :: SQLException:重复的列名:User_id:ALTER TABLE" comments"添加" User_id"整数/

时间:2014-09-10 18:26:06

标签: ruby sqlite

我运行了命令

rails g migration AddUser_idToComments User_id:string

然后我发现User_id应该是一个整数,所以我跑了

rails g migration AddUser_idToComments User_id:integer --force认为它会覆盖初始命令。

但是现在,我收到了这个错误:

``` louismorin $ rake db:migrate == 20140910155248 AddIndexToComments:迁移=============================== - add_column(:comments,:Index,:string)     - > 0.0069s == 20140910155248 AddIndexToComments:已迁移(0.0070s)======================

== 20140910181022 AddUserIdToComments:迁移============================== - add_column(:comments,:User_id,:integer) 耙子流产了! StandardError:发生错误,此以及所有后续迁移都已取消:

SQLite3 :: SQLException:重复的列名:User_id:ALTER TABLE“comments”ADD“User_id”integer / Users / louismorin / code / CP299 / db / migrate / 20140910181022_add_user_id_to_comments.rb:3:in change' ActiveRecord::StatementInvalid: SQLite3::SQLException: duplicate column name: User_id: ALTER TABLE "comments" ADD "User_id" integer /Users/louismorin/code/CP299/db/migrate/20140910181022_add_user_id_to_comments.rb:3:in更改“ SQLite3 :: SQLException:重复的列名:User_id /Users/louismorin/code/CP299/db/migrate/20140910181022_add_user_id_to_comments.rb:3:in`change' 任务:TOP => DB:迁移 (通过使用--trace运行任务查看完整跟踪) ```

这是我的schema.rb文件

```     ActiveRecord :: Schema.define(版本:20140910155210)做

create_table "comments", force: true do |t|
  t.text     "body"
  t.integer  "post_id"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "User_Id"
end

add_index "comments", ["post_id"], name: "index_comments_on_post_id"

create_table "posts", force: true do |t|
  t.string   "title"
  t.text     "body"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.integer  "user_id"
  t.integer  "topic_id"
end

add_index "posts", ["topic_id"], name: "index_posts_on_topic_id"
add_index "posts", ["user_id"], name: "index_posts_on_user_id"

create_table "topics", force: true do |t|
  t.string   "name"
  t.boolean  "public",      default: true
  t.text     "description"
  t.datetime "created_at"
  t.datetime "updated_at"
end

create_table "users", force: true do |t|
  t.string   "email",                  default: "", null: false
  t.string   "encrypted_password",     default: "", null: false
  t.string   "reset_password_token"
  t.datetime "reset_password_sent_at"
  t.datetime "remember_created_at"
  t.integer  "sign_in_count",          default: 0,  null: false
  t.datetime "current_sign_in_at"
  t.datetime "last_sign_in_at"
  t.string   "current_sign_in_ip"
  t.string   "last_sign_in_ip"
  t.string   "confirmation_token"
  t.datetime "confirmed_at"
  t.datetime "confirmation_sent_at"
  t.string   "unconfirmed_email"
  t.string   "name"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "role"
  t.string   "avatar"
  t.string   "Image"
end

add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique:     true

end

```

1 个答案:

答案 0 :(得分:0)

由于该错误,您的第二次迁移 - 更改列类型 - 未运行。如果该迁移仅用于更改该列,则我们可以删除它生成的文件并重试。

如果您还没有关注该列中的任何数据,那就非常简单了:

rails g migration ChangeTypeOfUserIdOnComments

  

此迁移名称并不特殊。可能也是DoWhateverIWant

然后,将创建的迁移的更改方法编辑为以下内容:

def change
  remove_column :comments, :user_id
  add_column :comments, :user_id, :integer
  add_index :comments, :user_id
end

当您运行未运行的迁移rake db:migrate时,它不应该在错误的迁移(因为我们删除它),然后它应该运行这一个,这将删除列并添加它以正确的类型返回。

如果您想要保存数据,则过程会更复杂。您的更改方法必须获取每个注释的当前user_id,然后在创建新列时将它们分配给新注释。希望以下工作:

def change
  user_ids = {}
  Comment.find_each{ |c| user_ids[c.id] = c.user_id.to_i } 

  remove_column :comments, :user_id
  add_column :comments, :user_id, :integer
  add_index :comments, :user_id
  Comment.each{ |c| c.update_attribute(:user_id, user_ids[c.id])
end

另请注意,命令中的迁移名称通常都是CamelCase或所有snake_case。所以:AddColumnUserIdToCommentsadd_column_user_id_to_comments。如此命名可能会导致问题。

**编辑**

Modify a Column's Type in sqlite3

似乎SQLite没有很好的方法来修改/删除列。我建议:

删除并重新启动SQLITe表

删除表,删除原始user_id迁移以及新建的有关删除旧user_id列的行,然后使用新迁移创建新表。如果你不关心你的数据,应该可以正常工作

切换到Postgres,这是Heroku使用的数据库。

这可能是一个好主意(因为您希望您的生产和本地数据库的行为相同),但可能容易出错。

在这里寻求指导 - Change from SQLite to PostgreSQL in a fresh Rails project