2010-04-16 72 views
1

我該如何做'選擇更新',然後'更新'行使用ruby oci8。選擇與紅寶石oci8更新

我有一個表中只有1個記錄的兩個字段counter1和counter2。我想從表中選擇值,然後通過使用select for update來鎖定行來增加它們。

謝謝。

回答

0

您需要確保autocommit在您的連接上設置爲false。這是關鍵。然後,你會做以下步驟:

  1. 做你的選擇與最終FOR UPDATE子句(選擇列1,列2從MYTABLE的更新)。這將鎖定該行。

  2. 執行您的更新查詢。

  3. 發出一個顯式提交,它將釋放行上的鎖。

當然要記住,鎖定行只是將其鎖定在修改狀態。另一個會話仍然可以查詢這些行。例如,如果這是一個ID,並且獲取新ID的方式是查詢執行select max(id) + 1 from table的表。鎖定行不會阻止另一個會話執行此選擇。

更好的辦法是跳過選擇並更新記錄,並使用returning子句向您返回新的更新值。我從來沒有在Ruby OCI8中做過,所以我不確定它是否支持該功能。在更新該條款的文檔是在這裏:

http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10007.htm#i2126358

+0

是的,我使用它作爲一個ID。我想選擇計數器的當前值(將其用作ID)並增加計數器。它是否阻止另一個會話執行「選擇更新」而不是「選擇」。使用'選擇更新'可以讓兩個會話仍然獲得相同的ID。我會嘗試'返回'條款。謝謝。 – user290870 2010-04-17 19:36:29

+0

@ ash34:如果一個會話完成了「select for update」並且尚未提交或回滾,另一個會話執行「select for update」將阻止等待能夠獲得鎖定。您可以使用'select for update nowait'快速地使其他會話失敗。請在此處查看nowait的簡短說明:http://docstore.mik.ua/orelly/oracle/prog2/ch06_11.htm – 2010-04-18 04:57:07

+1

如果您想要一個可靠的計數器,您應該使用一個序列。 – Martlark 2012-08-25 05:15:08

0
select_stmt = conn.prepare('select * from table_name for update') 
select_stmt.exec 
while row = select_stmt.fetch 
    conn.exec('update table_name set col = :1 where rowid = :2', 'val', select_stmt.rowid) 
end