25

私のgeneral_examsテーブルには、typeisという名前の列がありsemesterますstring。名前をに変更したいのですがsemester_id、タイプはintegerです。移行について読みましたが、利用可能な変換があります。

  • rename_column(table_name、column_name、new_column_name):列の名前を変更しますが、タイプとコンテンツは保持します。
  • change_column(table_name、column_name、type、options):add_columnと同じパラメーターを使用して、列を別のタイプに変更します。

したがって、次のように移行ファイルを作成します。

class RenameSemesterFromGeneralExams < ActiveRecord::Migration

  def change
    rename_column :general_exams, :semester, :semester_id
    change_column :general_exams, :semester_id, :integer
  end
end

しかし、実行するrake db:migrateと、エラーが発生します。

==  RenameSemesterFromGeneralExams: migrating =================================
-- rename_column(:general_exams, :semester, :semester_id)
   -> 0.0572s
-- change_column(:general_exams, :semester_id, :integer)
rake aborted!
An error has occurred, this and all later migrations canceled:

PG::Error: ERROR:  column "semester_id" cannot be cast to type integer
: ALTER TABLE "general_exams" ALTER COLUMN "semester_id" TYPE integer

テーブルGeneralExamで、すべてのデータを破棄しました。だから、誰でも私にそれをどのように行うことができますか?または、2つの移行ファイルを作成する必要がありますか?

4

5 に答える 5

19

これはRails4の時点で機能します

def change
  rename_column :general_exams, :semester, :semester_id
  change_column :general_exams, :semester_id, :integer
end
于 2015-05-26T08:57:26.730 に答える
12

問題はおそらく、semesterに変換できないデータが含まれていることintegersです。そのため、キャストエラーが発生します。

頭に浮かぶのは列を削除して正しい値で新しい列を作成することだけなので、これを機能させるにはさらに作業が必要だと思います。

ただし、1回の移行でremove_columnを削除してからadd_columnを実行するだけです。それは完璧に機能するはずです。

また、最初にadd_columnのみを実行してから、古いsemester値を新しい値にマップしてからsemester_id列をドロップするマッピングプロセスを実行することをお勧めします。

移行内でActiveRecordの操作を実行できることに注意してください。したがって、そのコードをそこに入れることができます。

于 2012-11-20T10:02:18.297 に答える
1

この助けを願っています

クラスModifyColumnTables
  デフチェンジ
    remove_column:posts、:old_column
    add_column:posts、:new_column、:type_of_column
  終わり
終わり
于 2018-02-11T02:36:59.337 に答える
0

このエラーは、PGが文字列から整数に変換する方法を知らない既存のデータ(またはデフォルト値、おそらく..)がテーブルにあるためです。データを削除するか、PG固有のSQL(必要になると思いますUSING)とexecute移行コマンドを使用して、データを変換する方法をPGに指示します。移行に関するRailsガイドを参照してください。

于 2012-11-20T10:06:15.507 に答える
0

これは、1回の移行で実行できます。ただし、これは常に機能するとは限らず、特にこのデータの変換方法を指定しない限り、列をブール型から整数型に、または文字列型から整数型に変換するときにエラーが発生する可能性があります。

つまり、general_examsテーブルにという列がsemesterあり、それは文字列です。名前をにsemester_id変更し、タイプを整数に変更します。

これを行う前に、作業がgitにコミットされていることを確認してください。そうすれば、いつでも古いコミットにリセットして、作業を失うことなく最初からやり直すことができます。

ターミナルで実行

rails g migration rename_the_column_semester_to_semester_id

これにより、移行が生成されます。次に、移行ファイルを開きます。

db/migrate/20210xxx_rename_the_column_semester_to_semester_id.rb

次のようになります。

class RenameTheColumnSemesterToSemesterID < ActiveRecord::Migration
  def change
  end
end

changeメソッド内で、ファイルを次のようにします。

class RenameTheColumnSemesterToSemesterID < ActiveRecord::Migration
  def change
    rename_column :general_exams, :semester, :semester_id
    change_column :general_exams, :semester_id, :integer, using: 'semester_id::integer'
  end
end

または、次のようにすることもできます。

class RenameTheColumnSemesterToSemesterID < ActiveRecord::Migration
  def change
    rename_column :general_exams, :semester, :semester_id
    change_column :general_exams, :semester_id, 'integer USING CAST(semester_id AS integer)'
  end
end

注重要: 上記は、列のテーブルにデフォルト値がない場合にのみ機能します。すでにデフォルト値を列に設定している場合でも、PG::DatatypeMismatch: ERROR: default for column "semester_id" cannot be cast automatically to semester integerPGが学期の列にすでにデフォルト値があると文句を言うようなエラーが発生するため、これは重要です。この場合、列の名前を変更して新しいデフォルト値を設定した後、デフォルト値を削除する必要があります。

class RenameTheColumnSemesterToSemesterID < ActiveRecord::Migration
  def change
    rename_column :general_exams, :semester, :semester_id
    execute "ALTER TABLE general_exams ALTER semester_id DROP DEFAULT;"
    change_column :general_exams, :semester_id, :integer, using: 'semester_id::integer', default: 1
  end
end

もちろん、モデルで0、1、2などから列挙している場合は、任意のデフォルト値を設定できます。

移行を保存します。実行します

rails db:migrate
于 2021-04-18T22:57:25.397 に答える