表一: //他的观点:
Prj ID Pre Nex OrderID //有人让帮忙实现以下功能,其中要用存储过程和游标
A 1 0 2 1 //一个表如是,Prj是元素,目的实现拖动排序。比如说将元素E"向上移
B 2 1 3 2 //动4位",变成下表。
C 3 2 4 3 //他的建议是移动一次,更改Pre和Nex,OrderID的值,进而进行排序。
D 4 3 5 4
E 5 4 0 5表二: Prj ID Pre Nex OrderID //我的观点:SUM(代表总列数)
E 1 0 2 1 //我认为不必在意Pre和Nex的值,只需要注意OrderID的值就行,比如
A 2 1 3 2 //将E上移4位,只需将未移动前的OrderID号在(X,Y)——X=SUM-要移动的
B 3 2 4 3 //位数,Y=被操作项的当前OrderId号,当前为(1,5)。将在区间的所有项的Or
C 4 3 5 4 //derId号加1,区间外的不变。最后再按ORDERID进行排序即可。
D 5 4 0 5
不知各位看法如何?我的想法是否可行,我考虑着是可以。如果各位认为我的想法可以,希望可以提出下。目前情况是我不是很懂存储过程,尤其是需要循环判断的存储过程,希望有人给个例子(不必对当前题目给出答案,只需要是个有循环的存储过程例子就行),谢谢!
Prj ID Pre Nex OrderID //有人让帮忙实现以下功能,其中要用存储过程和游标
A 1 0 2 1 //一个表如是,Prj是元素,目的实现拖动排序。比如说将元素E"向上移
B 2 1 3 2 //动4位",变成下表。
C 3 2 4 3 //他的建议是移动一次,更改Pre和Nex,OrderID的值,进而进行排序。
D 4 3 5 4
E 5 4 0 5表二: Prj ID Pre Nex OrderID //我的观点:SUM(代表总列数)
E 1 0 2 1 //我认为不必在意Pre和Nex的值,只需要注意OrderID的值就行,比如
A 2 1 3 2 //将E上移4位,只需将未移动前的OrderID号在(X,Y)——X=SUM-要移动的
B 3 2 4 3 //位数,Y=被操作项的当前OrderId号,当前为(1,5)。将在区间的所有项的Or
C 4 3 5 4 //derId号加1,区间外的不变。最后再按ORDERID进行排序即可。
D 5 4 0 5
不知各位看法如何?我的想法是否可行,我考虑着是可以。如果各位认为我的想法可以,希望可以提出下。目前情况是我不是很懂存储过程,尤其是需要循环判断的存储过程,希望有人给个例子(不必对当前题目给出答案,只需要是个有循环的存储过程例子就行),谢谢!
回复1楼,你可能没认清楚我的问题。第一种一点也不少,你看,在E变动期间,中间所有数的Pre和NEx都变了,这个是上下移动,并不仅仅是两者间的对调位置。所以我说,第一种根本就不省事。你说是吗?
if object_id('tempdb.dbo.#') is not null drop table #
create table #(Prj varchar(8), OrderID int)
insert into #
select 'A', 1 union all
select 'B', 2 union all
select 'C', 3 union all
select 'D', 4 union all
select 'E', 5--> 两个参数:元素, 移动步长
declare @Prj varchar(8), @Move int
set @Prj = 'C'
set @Move = -1 -- 负数表示向上移动,正数表示向下移动,循环移动
--> 过程部分
declare @offset int, @len int
select @offset = min(OrderID), @len = count(1) from #set @Move = (@Move % @len + @len) % @len -- 将向上移动转化为向下移动 简化逻辑if @Move>0
begin declare @OrderID int, @MoveTo int
select @OrderID = OrderID from # where Prj = @Prj -- 当前位置
set @MoveTo = @OrderID - @offset + @Move
set @MoveTo = @MoveTo % @len + @offset -- 要移动到的位置 declare @min int, @max int, @sign int -- 设置移动操作涉及的边界
if @MoveTo>@OrderID
select @min = @OrderID, @max = @MoveTo, @sign = -1
else
select @min = @MoveTo, @max =@OrderID , @sign = 1 -- 一次性更新 不需要循环或游标
update # set OrderID =
case OrderID
when @OrderID then @MoveTo
else OrderID + @sign
end
where OrderID between @min and @maxend--> 过程结束 检查数据 C 向上移动了1步
select * from # order by 2/*
Prj OrderID
-------- -----------
A 1
C 2
B 3
D 4
E 5
*/
改名字也很麻烦,不是简单的Current/MoveTo对调,当然用循环step by step可以这样干,这样更新数据库的次数就变多了。
if object_id('#TB') is not null drop table #TB
GO
create table TB(Prj varchar(1), ID int, Pre int, Nex int, OrderID int)
insert into TB
select 'A', 1, 0, 2, 1 union all
select 'B', 2, 1, 3, 2 union all
select 'C', 3, 2, 4, 3 union all
select 'D', 4, 3, 5, 4 union all
select 'E', 5, 4, 0, 5
GO
DECLARE @PRJ VARCHAR(8),@NUM INT
SELECT
@PRJ='E'
,@NUM=-3
UPDATE T1
SET T1.PRJ=
CASE WHEN T2.PRJ<>@PRJ THEN T1.PRJ
WHEN T2.PRJ=@PRJ THEN T2.PRJ
WHEN T2.PRJ IS NULL THEN T3.PRJ
END
FROM TB T1
LEFT JOIN TB T2 ON T1.ID=T2.ID+@NUM
LEFT JOIN TB T3 ON T3.ID=T1.ID-1SELECT * FROM TB
/*
A 1 0 2 1
E 2 1 3 2
B 3 2 4 3
C 4 3 5 4
D 5 4 0 5
*/
if object_id('TB') is not null drop table TB
if object_id('PROC_MU') is not null drop table PROC_MU
GO
create table TB(Prj varchar(1), ID int, Pre int, Nex int, OrderID int)
insert into TB
select 'A', 1, 0, 2, 1 union all
select 'B', 2, 1, 3, 2 union all
select 'C', 3, 2, 4, 3 union all
select 'D', 4, 3, 5, 4 union all
select 'E', 5, 4, 0, 5
GOCREATE PROCEDURE PROC_MU(@PRJ VARCHAR(8),@NUM INT)
AS
BEGIN
UPDATE T1
SET T1.PRJ=
CASE WHEN T2.PRJ<>@PRJ THEN T1.PRJ
WHEN T2.PRJ=@PRJ THEN T2.PRJ
WHEN T2.PRJ IS NULL THEN T3.PRJ
END
FROM TB T1
LEFT JOIN TB T2 ON T1.ID=T2.ID+@NUM
LEFT JOIN TB T3 ON T3.ID=T1.ID-1
END
GOEXEC PROC_MU 'E',-4
SELECT * FROM TB
/*
E 1 0 2 1
A 2 1 3 2
B 3 2 4 3
C 4 3 5 4
D 5 4 0 5
*/
这里ID代表某条新闻的ID,有可能临时插入或者删除一条新闻,所以ID不是连续的。