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 ...、インデックスも保持する and を実行します。

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

そのため、標準ドライバーは、実行時にインデックスを保持しrename_column、SQLite ドライバーはそのために何らかの努力をします。

ただし、API ドキュメントでは特定の動作を指定していないため、他のドライバーが他のことを行う場合があります。ドキュメントがインデックスについて何かを言うのに最も近いのは、次のactive_record/migration.rbとおりです。

rename_column(table_name, column_name, new_column_name): 列の名前を変更しますが、タイプと内容は保持します。

どのドライバーでもインデックスを保持すると思いますが、保証はありません。ドライバの作成者がインデックスを保持しないのは、確かに愚かなことです。

これは決定的または信頼できる回答ではありませんが、標準の PostgreSQL、MySQL (いずれか 1 つ)、または SQLite ドライバーを使用する場合は、インデックスを保持する必要があります。


インデックス自体は列の名前変更後も存続しますが、インデックスが変更されるという保証はないことに注意してください。これは、関連する列ではなくインデックス名を気にする何か (手動で削除するなど) を行っていない限り、問題にはなりません。

上記の動作は Rails 4 で変更されました

  • Rails 4.0 では、列またはテーブルの名前が変更されると、関連するインデックスの名前も変更されます。インデックスの名前を変更する移行がある場合、それらは不要になります。

そのため、ActiveRecord は、テーブルまたは列の名前を変更すると、新しいテーブルまたは列の名前に一致するようにインデックスの名前を自動的に変更します。これについて注意を喚起してくれたsequieloに感謝します。

于 2011-07-18T14:00:30.907 に答える