postgresql nextval, генерирующий существующие значения - PullRequest
6 голосов
/ 10 ноября 2009

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

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

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

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

'select max(id) from <table_name>' 

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

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

Ответы [ 5 ]

11 голосов
/ 10 ноября 2009

Существует метод 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, либо для конкретной модели, передав имя класса.

5 голосов
/ 08 апреля 2011

Версия 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

https://gist.github.com/909032

3 голосов
/ 10 ноября 2009

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

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

   ALTER SEQUENCE geopoints_id_seq RESTART with 1692;

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

1 голос
/ 10 ноября 2009

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

0 голосов
/ 10 ноября 2009

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

...