2012-04-16 77 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 

应该没有任何问题。