2013-03-13 117 views
1

我每天运行ruby脚本作业来将数据从一个表加载到另一个表,直到源表中找到重复的键记录为止,因为该表没有约束。我的目标表拒绝了这些记录,因为目标表对列具有主键约束(head_date,center_id,site_url)。我的程序刚刚停止,并在命令行中显示下面的错误。 :-(如何捕捉和忽略Ruby中的ActiveRecord :: RecordNotUnique异常

in `async_exec': PG::Error: ERROR: duplicate key value violates unique constraint "tst_data_pkey" (ActiveRecord::RecordNotUnique) 

我可以期待源表有其他讨厌的记录是这样的。我该如何继续处理,并抓住这个活动记录异常后移动到下一个记录?

下面是我更新/插入代码:

class SiteSection < ActiveRecord::Base 

    SiteSection.establish_connection(
     :adapter => 'postgresql', 
     :host  => 'hoster-of-hosts.com', 
     :database => 'super-inven', 
     :username => 'user', 
     :password => 'pass' 
        ) 
    self.table_name = 'master.target_tbl' # << insert into this table 
end 

conn.query("select * from source_tbl") do |row| 
    siteData = SiteSection.find_or_initialize_by_head_date_and_center_id_and_site_url(row[:date_c], row[:com_id], row[:site_link]) 

    siteData[:head_date]  = row[:date_c] 
    siteData[:center_id]  = row[:com_id] 
    siteData[:site_url]   = row[:site_link].nil? ? 'unknown' : row[:site_link] 
    siteData[:people_cnt]  = row[:persons].nil? ? 0 : row[:persons] 
    siteData[:ips]  = row[:ip_adds].nil? ? 0 : row[:ip_adds] 

    siteData.save 
i = i+1 
puts "finished: #{i}" if i % 10000 == 0 
end 
conn.close 

回答

3

您可以使用

begin 

rescue => e 

end 

像这个:

class SiteSection < ActiveRecord::Base 

    SiteSection.establish_connection(
     :adapter => 'postgresql', 
     :host  => 'hoster-of-hosts.com', 
     :database => 'super-inven', 
     :username => 'user', 
     :password => 'pass' 
        ) 
    self.table_name = 'master.target_tbl' # << insert into this table 
end 

conn.query("select * from source_tbl") do |row| 
    siteData = SiteSection.find_or_initialize_by_head_date_and_center_id_and_site_url(row[:date_c], row[:com_id], row[:site_link]) 

    siteData[:head_date]  = row[:date_c] 
    siteData[:center_id]  = row[:com_id] 
    siteData[:site_url]   = row[:site_link].nil? ? 'unknown' : row[:site_link] 
    siteData[:people_cnt]  = row[:persons].nil? ? 0 : row[:persons] 
    siteData[:ips]  = row[:ip_adds].nil? ? 0 : row[:ip_adds] 

    begin 
    siteData.save 
    rescue => e 
    puts e.message 
    puts "Error happened but I'll just keep chuggin along" 
    end 
i = i+1 
puts "finished: #{i}" if i % 10000 == 0 
end 
conn.close 

rescue => e预计会发生错误。它会通过不让它冒泡来吞噬这个错误。您的代码将继续运行,而不会异常崩溃。

+0

你确定它需要包含self.table_name ='master.target_tbl'吗?这是为什么?我认为它应该围绕它实际插入的部分或siteData.save命令。请让我知道逻辑,以便我能更好地理解..谢谢。 – Doublespeed 2013-03-13 04:07:35

+0

是的,它会在'save'上得到提升。固定 – AdamT 2013-03-13 04:28:55

-1

如果你有独特的钥匙,你应该使用它 - 是这样的:

i = 0 
puts 'loading records' 
conn.query("select * from source_tbl") do |row| 
    rec = SiteSection.where(
    :head_date => row[:date_c], 
    :center_id => row[:com_id], 
    :site_url => (row[:site_link] || 'unknown') 
).first_or_initialize 

    rec.people_cnt = (row[:persons] || 0) 
    rec.ips => (row[:ip_adds] || 0) 

    rec.save! 

    i += 1 
    print '.' if i % 10000 == 0 
end 
puts "done\ntotal records: #{i}" 

这样,您将节省(新)的记录或更新的人(如果找到)。没有ActiveRecord::RecordNotUnique应该在这里,如果你没有改变你的pkey!

+0

顺便说一句 - 如果你仍然有一个错误,你可以用户'开始...救援=> e ...结束“块。但你不应该在这里有一个错误;) – NilColor 2013-03-18 21:17:58

+0

嗯......为什么倒票?请留下评论。 – NilColor 2013-07-25 11:53:40