67

说,我们有这样的事情:

add_column :users, :single, :boolean
add_index :users, :single

然后我们做

rename_column :users, :single, :married

ActiveRecord 和/或数据库是否也会处理索引的重命名,还是我必须手动删除索引并再次添加它?

4

1 回答 1

106

对于 PostgreSQL,rename_column它被实现为一个简单的ALTER TABLE ... RENAME COLUMN ...并且确实保留了索引。

MySQL 版本(两者)都做了一个ALTER TABLE ... CHANGE ...并且还保留了索引。

SQLite 版本似乎复制了整个表(带有索引),删除了旧表,然后将副本复制回原始表名。复制似乎在复制索引时处理列重命名:

def copy_table(from, to, options = {})
  #...
  copy_table_indexes(from, to, options[:rename] || {})

和里面copy_table_indexes

columns = index.columns.map {|c| rename[c] || c }.select do |column|
  to_column_names.include?(column)
end

因此,当您执行 a 时,标准驱动程序将保留您的索引,rename_column而 SQLite 驱动程序会努力这样做。

API 文档没有指定任何特定的行为,因此其他驱动程序可能会做其他事情。文档中最接近于说明索引的内容是active_record/migration.rb

rename_column(table_name, column_name, new_column_name):重命名列但保留类型和内容。

我认为任何驱动程序都会保留索引,但不能保证;驱动程序编写者不保留索引肯定是愚蠢的。

这不是一个明确或权威的答案,但如果您使用标准 PostgreSQL、MySQL(其中之一)或 SQLite 驱动程序,则应保留您的索引。


请注意,即使索引本身在列重命名后仍然存在,也不能保证索引名称会被更改。这应该不是问题,除非您正在做一些关心索引名称而不是涉及哪些列的事情(例如手动删除它)。

Rails 4 中的上述行为发生了变化:

  • 在 Rails 4.0 中,当重命名列或表时,相关索引也会重命名。如果您有重命名索引的迁移,则不再需要它们。

因此,当您重命名表或列时,ActiveRecord 会自动重命名索引以匹配新的表或列名。感谢sequielo 对此的提醒。

于 2011-07-18T14:00:30.907 回答