postgresql nextval生成现有值

Dan*_*son 6 postgresql ruby-on-rails auto-increment nextval

我不得不从rails app上的基于mySql的ruby迁移到使用postgresql.到目前为止没有问题,但我不知道如何解决它.

数据的迁移带来了id,而postgresql现在遇到了现有ID的问题:我不清楚它在哪里获得用于确定nextval基数的值:它肯定不是最高值专栏,虽然您可能认为这是一个好主意.无论如何,它现在与现有的id值发生冲突.从标准RoR迁移创建的id列定义为

not null default nextval('geopoints_id_seq'::regclass)
Run Code Online (Sandbox Code Playgroud)

是否有一些地方可以将其作为基础使用的价值入侵?这个问题现在可能出现在20个左右的表格中:我可以使用

'select max(id) from <table_name>' 
Run Code Online (Sandbox Code Playgroud)

但这似乎使自动增量柱的想法毫无意义.

如何最好地处理?

hgm*_*mnz 11

Postgres适配器有一种reset_pk_sequences!方法.你可以调用它,它会将它设置为max(id)+ 1,这可能是你想要的.

在某些项目中,我经常获得ETL数据,以保证所有模型或指定模型的rake任务.这是任务 - 将它包含在一些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
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用所有模型(在RAIS_ROOT/app/models下定义)rake reset_sequences或通过传入类名来为特定模型运行此模型.


小智 5

rails 3版本看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

https://gist.github.com/909032

  • 我认为`RAILS_ROOT`应该是`Rails.root.to_s`.此外,不推荐使用`task`语法.我认为它应该是`task:reset_sequences,[:model_class] => [:environment]` (2认同)