postgresql nextval генерирует существующие значения

Мне пришлось перейти от приложения ruby ​​on rails на основе mySql к использованию postgresql. Пока никаких проблем, но я не знаю, как их решить.

Миграция данных принесла с собой идентификаторы, и у postgresql теперь есть проблемы с существующими идентификаторами: мне не ясно, где он получает значение, которое он использует для определения базы для следующего значения: это, конечно, не самое высокое значение в колонка, хотя вы можете подумать, что это будет хорошая идея. В любом случае, теперь он сталкивается с существующими значениями идентификатора. Столбец id, созданный из стандартной миграции RoR, определяется как

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

Есть ли место, где значение, которое оно использует в качестве основы, можно взломать? Эта проблема теперь может возникнуть в любой из 20 или около того таблиц: я мог бы использовать

'select max(id) from <table_name>' 

но это, кажется, делает идею колонки автоинкремента бессмысленной.

Как это лучше всего обрабатывается?

5 ответов

Решение

E сть reset_pk_sequences! метод на адаптере Postgres. Вы можете вызвать его, и он установит его в 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или для конкретной модели, передавая имя класса.

Версия рельсов 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

https://gist.github.com/909032

С этим определением столбец получит следующее значение из последовательности geopoints_id_seq. Эта последовательность непосредственно не привязана к таблице. Если вы переносите данные, вы должны создать или обновить эту последовательность, чтобы ее начальная точка была больше, чем текущий максимальный идентификатор в вашей таблице.

Вы должны быть в состоянии установить его новое значение с помощью, например,

   ALTER SEQUENCE geopoints_id_seq RESTART with 1692;

Или как выбрать max(id) из table_name; доходность

PG использует последовательности:

Сделайте так, чтобы его текущее значение было на 1 больше, чем самое высокое значение в вашей таблице.

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

Также посмотрите эти

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

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

Используйте setval(), чтобы установить начальное значение для последовательности.

Другие вопросы по тегам