2013-10-15 34 views
4

我有一個表中的SQLite 3從而:模擬ORDER BY SQLite中UPDATE處理唯一性約束

sqlite> .schema 
CREATE TABLE table1 (id INTEGER PRIMARY KEY NOT NULL, 
        title TEXT UNIQUE NOT NULL, 
        priority INTEGER UNIQUE NOT NULL); 

下面是一些示例數據,爲了說明:

sqlite> SELECT * FROM table1; 
id   title  priority 
---------- ---------- ---------- 
1   a   1   
2   b   2   
3   c   3   
4   d   4 

我希望添加1所有細胞的prioritypriority > 1。這是我第一次嘗試:

sqlite> UPDATE table1 SET priority = priority + 1 WHERE priority > 1; 
Error: column priority is not unique 

此操作失敗,可能是因爲更新不下令,允許UPDATE嘗試集合中的小區之一,在priority列到現有的單元格的值。所以,這裏是我的第二次嘗試:

sqlite> UPDATE table1 SET priority = priority + 1 WHERE priority > 1 
     ORDER BY priority DESC; 
Error: near "ORDER": syntax error 

這也失敗了,大概是因爲我的SQLite 3的安裝沒有與SQLITE_ENABLE_UPDATE_DELETE_LIMIT選項編譯。

,因爲我可能最終想用我的SQL語句(S)與Android的SQLite,而後者也does not啓用SQLITE_ENABLE_UPDATE_DELETE_LIMIT,我有更好的找到另一種方式來實現我的目標不是重新編譯的SQLite 3 SQLITE_ENABLE_UPDATE_DELETE_LIMIT啓用。那麼,這裏是我的第三次嘗試:

sqlite> BEGIN TRANSACTION; 
     UPDATE table1 SET priority = priority + 1 WHERE priority > 1; 
     END TRANSACTION; 
Error: column priority is not unique 

這也失敗了,大概是因爲SQLite的提交事務之前檢查的唯一性約束。

三次失敗的嘗試,但我相信這是可能的。問題是:怎麼辦呢;在那之內,如何最好地做到這一點

N.B.我寧願不依賴任何未經檢查的假設。

回答

7

問題的出現是因爲SQLite在每次行更新後檢查約束,而不是在語句結束或事務結束時檢查約束。

我看到這個問題的解決方法(SQLite沒有正確實施UPDATE)。假設priority列沒有任何負面的值,我們可以使用它們(負值)爲臨時避免UNIQUE約束錯誤:

UPDATE table1 SET priority = - (priority + 1) WHERE priority > 1 ; 

UPDATE table1 SET priority = - priority WHERE priority < 0 ; 
+0

有趣的;謝謝!我不知道'優先'不會包含負值的假設是否成立,所以儘管我已經提出了你的答案,但我還沒有將其標記爲「已接受」。我一直在考慮嘗試COUNT來建立一個偏移以避免衝突,但是這種方法的成功取決於一個不同的假設(即「優先級」中的值不會大於優先級中的值'保證連續),我再次不確定的正確性。我寧願一個不依賴假設的解決方案。 – sampablokuper

+0

(或者更具體地說,在未檢查的假設下。) – sampablokuper

+0

我以爲你是這個數據庫/應用程序的設計者或開發者,所以你知道需求/假設。 –