SQL:更新组中用户有序的项目序列

时间:2017-09-18 07:48:19

标签: sql sql-server

用于以特定顺序存储与容器相关联的项目的表。单独的涉及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作为新记录附加。

1 个答案:

答案 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