如何实现数据在表内部置顶

先考虑按SortId降序排列的情况。初始状态SortId=Id

方案1,首先获取当前最大的SortId,例如:@MaxSid = 100

其次,将要置顶的行重新升序排列放入表变量里,并添加一列序号列

select row_number() over(order by sortid) as NId,Id,SortId 
from T_Test
where id in(11,22,33,44)
order by sortid


结果:

NId Id SortId
1 11 11
2 22 22
3 33 33
4 44 44

 

 

 

 

 

然后,计算出新的SortId=@MaxSid+NId

declare @t table(nid int,id int)

insert into @t
select row_number() over(order by sortid) as NId,Id
from T_Test
where id in(11,22,33,44)
order by sortid


update T_Test set SortId = @MaxSid + b.nid
from T_Test as a
join @t as b on a.id=b.id
where a.id in(11,22,33,44)

结果:

NId Id SortId
1 11 101
2 22 102
3 33 103
4 44 104

 

 

 

 

 

此方法,会导致SortId无限增加,有可能造成溢出

另外,有的情况可能有要求,必须使用现有的SortId。这就需要将最大的SortId赋给要置顶的目标。顶部和目标之间的项依次下降。

 

方案2,先针对单条数据的位置移动写一个存储过程

P_Swt(原始SortId,目标SortId)

然后取出所有要置顶的元素,遍历

调用 P_Swt(原始SortId,最大SortId递减)

 

代码先不写了,这个方法在逻辑上比较好理解,也好维护,有一定复用性,比较灵活,

但是比较浪费性能

每次遍历都需要将很多数据的SortId减一,很多数据会重复多次减一这个动作

 

方案3,将要置顶的数据中SortId最小也就是最底部的数据一直到全部数据中最大的SortId,之间的SortId分区。

这样,不同区间要下降的位移不同的,每个区间移动一次就可以了

例如:要置顶 11,22,33,44

可以写成:

update T_Test set SortId=SortId-1 where SortId>44 and SortId<=@MaxSid

update T_Test set SortId=SortId-2 where SortId>33 and SortId<44

update T_Test set SortId=SortId-3 where SortId>22 and SortId<33

update T_Test set SortId=SortId-4 where SortId>11 and SortId<22

然后,按照方案一移动目标数据就可以了

所以剩下的就是如何自动生成上边的脚本了

是不是只能遍历呢?

好像是的。

游标编列或是数组遍历都可以

数组方案:

http://blog.csdn.net/fuyouhu2008/article/details/5150625

唯一要注意的就是第一条脚本生成的时候需要处理一下,或者遍历之前直接将(@MaxSid+1)插入到要遍历的数据中

这样脚本模板比较好写了,从第二条可是遍历

update T_Test set SortId = SortId - i where SortId>@Current and SortId<@Prev

 

此方案需要较多逻辑处理,和方案一一样不利于维护。复用性不高。

 

结束。

Ps:既然必定要一次更新很多条数据,而且除了方案一都会对此更新,并发是不可避免的问题。

如何处理并发呢?

锁定表? 好像可以,但不利于用户体验

锁定置顶按钮? 也就是,置顶的时候如果堵塞,返回置顶失败,这样只有第一个可以置顶成功。

posted on 2012-03-20 13:20  人在做,人在看  阅读(781)  评论(1编辑  收藏  举报