2012-04-16 86 views
0

給定一個像這樣的表,其中x和y具有唯一約束。已訂購SQL更新

 
id,x,y 
1, 1,1 
2, 1,2 
3, 2,3 
4, 3,5 
.. 

我想用UPDATE語句將一組行中的值x和y增加一個固定量。假設我將它們都增加了1,看起來UPDATE按照id順序,並且在用1 2更新行之後給我一個錯誤,因爲它碰到了下一行,2 3,它還沒有更新到3,4然而。

谷歌搜索,我無法找到強制更新使用訂單的方法。要做到這一點就足夠了我的應用程序。我也確信整個更新之後這個集合是一致的。

任何解決方案?有什麼方法可以強制訂單進入更新或以任何方式推遲約束檢查,直到完成?

這是爲了Django應用程序,它意味着與所有支持的數據庫兼容。我知道一些數據庫具有原子事務並且這個問題不會發生,有些功能可以避免這個問題,但我需要一個嚴格標準的SQL解決方案。

+1

哪個DBMS? PostgreSQL的?甲骨文? DB2? – 2012-04-16 17:07:26

+1

歡迎來到StackOverflow。當問一個SQL問題時,如果你還爲你正在使用的數據庫添加一個標籤,它會有所幫助。它們之間的語法和功能有所不同,如果你這樣做,你會更快得到一個有用的答案。你現在可以編輯你的問題來添加它。謝謝。 :) – 2012-04-16 17:09:29

+0

正如我在obs中所說的,這是爲了一個Django應用程序,它意味着與所有支持的數據庫一起使用,所以通用解決方案更好。我正在開發使用SQLite進行測試,但是從'a_horse_with_no_name'給出的答案我認爲這個問題不會發生在Oracle中。 – 2012-04-16 17:46:09

回答

1

對於PostgreSQL,您可以將主鍵約束定義爲「可延遲」,然後僅在提交時對其進行評估。

在PostgreSQL這應該是這樣的:

postgres=>create table foo (
postgres(> id integer not null, 
postgres(>  x integer, 
postgres(>  y integer 
postgres(>); 
CREATE TABLE 
postgres=>alter table foo add constraint pk_foo primary key (id) deferrable initially deferred; 
ALTER TABLE 
postgres=> insert into foo (id, x,y) values (1,1,1), (2,1,1), (3,1,1); 
INSERT 0 3 
postgres=> commit; 
COMMIT 
postgres=> update foo set id = id + 1; 
UPDATE 3 
postgres=> commit; 
COMMIT 
postgres=> select * from foo; 
id | x | y 
----+---+--- 
    2 | 1 | 1 
    3 | 1 | 1 
    4 | 1 | 1 
(3 rows) 
postgres=> 

對於Oracle,這是沒有必要的,因爲它會評估UPDATE語句作爲單個原子操作,使開箱那裏。

+0

這不是主鍵,它是(x,y)對的唯一約束,但我明白了。 – 2012-04-16 17:56:45

+0

@pjwerneck:唯一約束與主鍵基本相同。 – 2012-04-16 18:22:48

0

爲了方便參考,MS SQL Server也不會出現這個問題。 UPDATE是一個單一的原子操作。

ALTER TABLE [table_name] 
ADD CONSTRAINT unique_constraint 
UNIQUE(x) 

ALTER TABLE [table_name] 
ADD CONSTRAINT unique_constraint2 
UNIQUE(y) 

update [table_name] 
set x = x+1, 
y = y+1 

應該沒有任何問題。