2014-03-01 122 views
0

我使用sqlite ON CONFLICT ROLLBACK子句來保留一個可能佔用的資源表。這是通過重複的陳述來完成的,這些陳述在交易中非常有意義。像這樣:sqlite ON CONFLICT ROLLBACK和連續查詢

BEGIN TRANSACTION; 
INSERT INTO places (place) VALUES(17); 
INSERT INTO places (place) VALUES(18); 
INSERT INTO places (place) VALUES(19); 
COMMIT; 

這些地方受限於... place UNIQUE ON CONFLICT ROLLBACK ...子句。

但是,似乎交易不是這個用途的理智。事實上,如果有一個衝突觸發器,即使我們沒有觸發COMMIT聲明,交易也會回滾。在COMMITCOMMIT之前的以下語句本身被執行,看起來,現在作爲具有隱式提交的單個語句。這種行爲有沒有用?我希望在調用COMMITROLLBACK產生BEGIN之前的狀態(如果被觸發)之前不會發生任何事情。

這是爲什麼?

回答

0

衝突解決子句的範圍始終是當前語句,而不是以下任何語句。 這適用於documented

程序在遇到錯誤時修復造成錯誤的任何內容並重試語句或執行其他語句是很常見的。 因此,數據庫假定您執行的任何命令都是您實際想要執行的命令。

ON CONFLICT ROLLBACK子句對您的應用程序沒有意義。 您應該使用正常導通衝突ABORT算法,要麼通過不執行任何以下命令處理衝突:

try: 
    db.execute("BEGIN") 
    db.execute("INSERT INTO places(place) VALUES(17)") 
    db.execute("INSERT INTO places(place) VALUES(18)") 
    db.execute("INSERT INTO places(place) VALUES(19)") 
    db.execute("COMMIT") 
except: 
    db.execute("ROLLBACK") 

或插入一個語句的所有值,以使任何自動中止回滾其他值:

INSERT INTO places(place) VALUES (17), (18), (19) 
+0

好的,但是使用一個語句明顯不能使用多個語句,例如不能混合使用INSERT和UPDATE,或者同時修改多個表。並且在每個查詢之後檢查錯誤是否會導致異常操作,其中我的應用程序發送了一堆針對sqlite3二進制文件的查詢。 – dronus

+0

另外它很有趣,當可能衝突的查詢作爲最後一個發出時,事實上'ROLLBACK'在發生衝突之前發出的任何查詢,將其置於事務中間時不會給出該功能...... – dronus

+0

所以,一個實際上可以結合不同的陳述,只要可能的衝突只有一個,最後發佈。 – dronus