2009-11-10 59 views
6

我必須從基於mySql的Rails應用程序遷移到使用postgresql。目前爲止沒有問題,但我不知道如何解決它。postgresql nextval生成現有值

數據的遷移帶來了ids以及postgresql現在的問題與現有的ids:我不清楚它在哪裏得到它用來確定nextval的基礎的價值:它當然不是雖然你可能認爲這是一個好主意,無論如何,它現在與現有的id值相沖突。從標準RoR遷移創建的id列定義爲

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

是否有某個地方可能會黑客使用它作爲基礎的值?現在可能出現這個問題在任何20個左右的表:我可以用

'select max(id) from <table_name>' 

,但似乎使自動增量列無謂的念頭。

這最好的處理方式是什麼?

回答

11

Postgres adapter上有reset_pk_sequences!方法。你可以調用它,它會將它設置爲max(id)+ 1,這可能是你想要的。

在一些項目中,我經常得到的ETL數據足以保證所有模型或特定模型都能執行此操作。這裏的任務 - 包括在一些Rake文件或在它自己下的lib /任務:

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解決方案,因爲我在Rails環境中,但我認爲這個消息是我可以通過postgres中的命令行來完成。 作爲後續工作:我要試一試,但我可以將這樣的聲明放入遷移中嗎? – 2009-11-10 18:57:40

+0

當然,你可以進行遷移:ActiveRecord :: Base.connection.reset_pk_sequence!('table_name'),但是這當然也可以從psql完成。 – hgmnz 2009-11-10 21:15:45

+0

精彩的+1積分 – kikito 2010-02-26 19:50:33

0

使用setval()來設置序列的起始值。

3

根據該定義,該列將從geopoints_id_seq序列中獲取下一個值。 該序列不直接附加到表格上。如果要遷移數據,則必須創建或更新該序列,以便其起點大於表中當前的最大ID。

您應該可以使用例如

ALTER SEQUENCE geopoints_id_seq RESTART with 1692; 

或者無論從table_name中選擇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:reset_sequences,[:model_class] => [:environment]' – 2011-11-07 01:35:59