用于以特定顺序存储与容器相关联的项目的表。单独的涉及item_id和seq的ak_ *约束确保容器包含不同的项目,并且这些项目的顺序是不同的。
CREATE TABLE [container_items] (
[container_item_id] INT IDENTITY (1, 1) NOT NULL,
[container_id] INT NOT NULL,
[item_id] INT NOT NULL,
[seq] INT NOT NULL,
CONSTRAINT [pk_container_item] PRIMARY KEY CLUSTERED ([container_item_id] ASC),
CONSTRAINT [ak_container_item_seq] UNIQUE NONCLUSTERED ([container_id] ASC, [seq] ASC),
CONSTRAINT [ak_container_item_item] UNIQUE NONCLUSTERED ([container_id] ASC, [item_id] ASC),
CONSTRAINT [fk_container_item_item] FOREIGN KEY ([item_id]) REFERENCES [items] ([item_id]),
CONSTRAINT [fk_container_item_container] FOREIGN KEY ([container_id]) REFERENCES [containers] ([container_id])
);
假设对于container_id = 1,原始数据为
container_item_id, container_id, item_id, seq
1,1,1,1
2,1,3,2
3,1,10,3
4,1,8,4
和一些用于重新排序的客户端应用程序说明item_ids的新序列是
8,1
10,2
3,3
1,4
ak_ *约束使得无法直接更新数据库表。例如,以这种方式尝试更新:
update container
container_items
set item_id=8, seq=1
where container_item_id = 1
失败
Violation of UNIQUE KEY constraint ak_container_item_item. Cannot insert duplicate key in object 'container_items'. The duplicate key value is (1, 8).
The statement has been terminated.
问:在更改seq顺序时,是否值得努力找到一种能够重用现有container_item_id记录的算法?
不可重用的方法是删除survery_id = 1的现有记录,然后将新的序列item_ids作为新记录附加。
答案 0 :(得分:1)
您可以在简单的原子事务中封装整个操作。此外,您还需要一个至少一个' aux'值,我在此示例中使用简单* -1
操作的几个辅助值:
begin transaction tx1;
set transaction isolation level serializable;
update container
survey_items
set seq=-1*seq #<-- set aux values
where container_id = 1;
update container
survey_items
set seq=1
where container_id = 1 and item_id = 8;
update container
survey_items
set seq=2
where container_id = 1 and item_id = 10;
#and so on
commit;
请注意,您可以repeatable read
使用相同的保证工作,因为没有phantoms。