6

mySqlベースのrubyonrailsアプリからpostgresqlを使用するように移行する必要がありました。今のところ問題はありませんが、解決方法がわかりません。

データの移行によりIDが一緒にもたらされ、postgresqlは既存のIDに問題を抱えています。nextvalのベースを決定するために使用する値をどこで取得するかはわかりません。確かに、列ですが、それは良い考えだと思うかもしれません。いずれにせよ、現在は既存のid値と衝突しています。標準のRoR移行から作成されたid列は、次のように定義されます。

not null default nextval('geopoints_id_seq'::regclass)

ベースとして使用する価値をハッキングできる場所はありますか?この問題は、20個程度のテーブルのいずれかで発生する可能性があります。

'select max(id) from <table_name>' 

しかし、それは自動インクリメント列のアイデアを無意味にするようです。

これはどのように処理するのが最適ですか?

4

5 に答える 5

11

Postgresアダプタreset_pk_sequences!にはメソッドがあります。あなたはそれを呼び出すことができ、それはそれをmax(id)+ 1に設定します、それはおそらくあなたが望むものです。

一部のプロジェクトでは、すべてのモデルまたは指定されたモデルに対してこれを実行するためのレーキタスクを保証するのに十分な頻度でデータをETLで取得します。タスクは次のとおりです。Rakefileまたはlib/tasksの下の独自のファイルに含めます。

desc "Reset all sequences. Run after data imports"
task :reset_sequences, :model_class, :needs => :environment do |t, args|
  if args[:model_class]
    classes = Array(eval args[:model_class])
  else
    puts "using all defined active_record models"
    classes = []
    Dir.glob(RAILS_ROOT + '/app/models/**/*.rb').each { |file| require file }
    Object.subclasses_of(ActiveRecord::Base).select { |c|
      c.base_class == c}.sort_by(&:name).each do |klass|
        classes << klass
      end
  end
  classes.each do |klass|
      next if klass == CGI::Session::ActiveRecordStore::Session && ActionController::Base.session_store.to_s !~ /ActiveRecordStore/

        puts "reseting sequence on #{klass.table_name}"
        ActiveRecord::Base.connection.reset_pk_sequence!(klass.table_name)
    end
end

これで、を使用してすべてのモデル(RAIS_ROOT / app / modelsで定義)に対してrake reset_sequences、またはクラス名を渡すことによって特定のモデルに対してこれを実行できます。

于 2009-11-10T18:22:38.193 に答える
5

Rails3バージョンは次のようになります。

namespace :db do
  desc "Reset all sequences. Run after data imports"
  task :reset_sequences, :model_class, :needs => :environment do |t, args|
    if args[:model_class]
      classes = Array(eval args[:model_class])
    else
      puts "using all defined active_record models"
      classes = []
      Dir.glob(RAILS_ROOT + '/app/models/**/*.rb').each { |file| require file }
      ActiveRecord::Base.subclasses.select { |c|c.base_class == c}.sort_by(&:name).each do |klass|
        classes << klass
      end
    end
    classes.each do |klass|
      puts "reseting sequence on #{klass.table_name}"
      ActiveRecord::Base.connection.reset_pk_sequence!(klass.table_name)
    end
  end
end

https://gist.github.com/909032

于 2011-04-08T00:05:42.880 に答える
3

その定義により、列はgeopoints_id_seqシーケンスから次の値を取得します。そのシーケンスは、テーブルに直接関連付けられていません。データを移行する場合は、そのシーケンスを作成または更新して、その開始点がテーブル内の現在の最大IDよりも大きくなるようにする必要があります。

たとえば、新しい値を設定できるはずです。

   ALTER SEQUENCE geopoints_id_seq RESTART with 1692;

または、table_nameからmax(id)を選択します。収量

于 2009-11-10T17:37:12.397 に答える
1

PGはシーケンスを使用します:

このように、現在の値をテーブルの最大値より1高くします。

SELECT setval('geopoints_id_seq', 999999999, true);

こちらもご覧ください

http://www.postgresql.org/docs/8.4/interactive/datatype-numeric.html#DATATYPE-SERIAL

http://www.postgresql.org/docs/8.4/interactive/functions-sequence.html

于 2009-11-10T17:33:41.953 に答える
0

setval()を使用して、シーケンスの開始値を設定します。

于 2009-11-10T17:35:23.353 に答える