2009-11-10 3 views
6

레일즈 애플리케이션의 mySql 기반 루비에서 postgresql을 사용하여 마이 그 레이션해야했습니다. 지금까지 문제는 없지만 해결 방법을 모르겠습니다.postgresql 기존 값 생성

데이터 마이그레이션시 id가 함께 가져오고 postgresql에서 기존 ID에 문제가 발생했습니다. nextval에 대한 기준을 결정하는 데 사용되는 값이 어디에서 발생하는지 분명하지 않습니다. 비록 당신이 좋은 생각이라고 생각할지 모르지만, 칼럼에서 가장 높은 가치. 어쨌든 현재 id 값과 충돌하고 있습니다. 표준 RoR 마이그레이션에서 생성 된 ID 열은

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

으로 정의됩니다. 기본으로 사용하는 값을 해킹 할 수있는 곳이 있습니까? 내가

'select max(id) from <table_name>' 

를 사용할 수 있지만 그 의미가 자동 증가 컬럼의 아이디어를 만들 것으로 보인다 :이 문제는 지금 20 개 정도 모든 테이블에서 발생할 수 있습니다.

어떻게 처리하는 것이 가장 좋습니까?

답변

11

Postgres adapter에는 reset_pk_sequences! 방법이 있습니다. 그것을 호출하면 max (id) + 1로 설정되며, 이는 아마도 원하는 것입니다.

일부 프로젝트에서는 모든 모델 또는 지정된 모델에 대해 rake 태스크를 수행 할 수 있도록 데이터를 자주 ETL 처리합니다. 여기에 작업입니다 - lib 디렉토리/작업에서 일부 Rakefile 또는 그 자체에 포함 :

이제
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 

당신이 rake reset_sequences를 사용하여 (RAIS_ROOT/응용 프로그램/모델에 정의) 모든 모델 또는 특정에 대해 하나이를 실행할 수 있습니다 클래스 이름을 전달하여 모델을 만듭니다.

+0

와우, 감사합니다. 레일 환경에 있기 때문에 @hgimenez 솔루션에서 실행 해 보겠다.하지만 메시지를 postgres의 명령 줄을 통해 처리 할 수 ​​있다고 가정합니다. 후속 조치 :이 방법을 시도 하겠지만 마이그레이션에 그러한 진술을 사용할 수 있습니까? –

+0

확실히, ActiveRecord :: Base.connection.reset_pk_sequence ('table_name')로 마이그레이션 할 수 있습니다. 그러나 이것은 psql에서도 확실히 수행 할 수 있습니다. – hgmnz

+0

awesomeness +1 점 – kikito

3

해당 정의가있는 열은 geopoints_id_seq 시퀀스에서 다음 값을 가져옵니다. 해당 시퀀스는 테이블에 직접 연결되지 않습니다. 데이터를 이전하는 경우 시작점이 테이블의 현재 최대 ID보다 커지도록 해당 순서를 생성하거나 업데이트해야합니다.

예를 들어 다음과 같이 새 값을 설정할 수 있습니다.

ALTER SEQUENCE geopoints_id_seq RESTART with 1692; 

또는 table_name의 select max (id) 수율

5

레일 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

+2

'RAILS_ROOT'는'Rails.root.to_s'이어야한다고 생각합니다. 또한,'task' 구문은 더 이상 사용되지 않습니다. 나는 그것이'task : reset_sequences, [: model_class] => [: environment]'이어야한다고 생각한다. –