2009-10-19 29 views
1

我有一個超過一千個鍵/值對的哈希。從一個哈希更新許多行而不只是循環在Rails中

我有一個數千行的數據庫表。

因此,蠻力的基於散列表的更新非常簡單。例如:

my_hash.each{|key,value| 
    Model.update_all("column2 = #{value}", "column1 = #{key}") 
} 

但是,這會做超過一千個SQL更新語句。

有沒有什麼好的方法(在Rails中)使用一個(或幾個)更新語句來完成此操作?

回答

2

好吧,我已經用Mike Woodhouse和ttarchala的提示解決了這個問題。下面的代碼(我用的是Ruby Sequel gem

# connect to the database 
DB = Sequel.connect("postgres://user:[email protected]/blah") 

# create the temporary table 
DB.create_table :temp_update, :temp => true do 
    primary_key :key 
    String :value 
end 

# insert rows from the hash (multi_insert takes an array of hashes,hence the map) 
DB[:temp_update].multi_insert(my_hash.map{|k,v| {:key => k, :value => v}}) 

# Do the update based on a join 
DB.execute(" UPDATE my_table 
       SET column2 = temp_update.value 
       FROM temp_update 
       WHERE column1 = temp_update.id") 

我使用Postgres的,所以確切的更新SQL可能是其他RDBMS不同。

-1

是的。我不知道具體是對鐵軌,但你可以使用SQL關鍵字,它的工作原理是:

select * from table where column in ('list', 'of', 'values') 
+0

這不是一個更新 – DanSingerman

+0

我會幫他:更新表SET字段=值,field2 = value2 WHERE id在(3,8,33,756,6543,54637) – chrishomer

3

最快的方法 - 在任何語言,不知道它是如何在Rails中做專門 - 將把你的內存散列轉儲到數據庫中的一個臨時表中,該數據庫只有你的散列鍵和值的列,然後發出一個UPDATE命令,並加入一個連接你的表的新的臨時表。

檢查查詢計劃以確保優化器按原樣工作,在發佈更新之前在臨時表上構建一個臨時索引。如果不是,請自行構建索引。

+0

+1,但是,這隻會工作如果你可以加載你的哈希表比你更快地運行更新 – cjk

+0

謝謝。我知道這種方法,但不知道如何在Rails中:( – DanSingerman

2

我不確定「好」,但在許多DBMS平臺上,可以在一次執行中發送多個SQL語句。例如,ar-extensions gem可以幫助批量INSERT語句,儘管取決於平臺可能需要稍微調整 - 例如,Oracle有點棘手。我不認爲它直接處理UPDATE,但你可以從這裏的另一個答案使用臨時表技巧:批量加載數據並使用ActiveRecord.execute運行UPDATE。在某種意義上說,它可能是可能的,但話又說回來,滑軌(或者更準確的ActiveRecord)從未打算將ORM功能用於絕對一切

可能只有「好」的,這就是爲什麼存在之類的東西find_by_sql:他們當你知道一個更好的方法時,在那裏度過。

+0

我已經使用了ar-extensions,它效果很好。 – semanticart