表一:                                  //他的观点:
 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.   


    回复1楼,你可能没认清楚我的问题。第一种一点也不少,你看,在E变动期间,中间所有数的Pre和NEx都变了,这个是上下移动,并不仅仅是两者间的对调位置。所以我说,第一种根本就不省事。你说是吗?
      

  2.   

    第一种,有点像链表,断链很难搞的,并不仅仅是修改2条数据。个人偏向第二种,不需要维护pre/next,一个OrderID搞定。
      

  3.   

    --> 测试数据:#
    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
    */
      

  4.   

    ID如果是连续的话可以用ID作排序列
      

  5.   


    改名字也很麻烦,不是简单的Current/MoveTo对调,当然用循环step by step可以这样干,这样更新数据库的次数就变多了。
      

  6.   

    if object_id('TB') is not null drop table TB
    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
    */
      

  7.   

    改成LZ要的存储过程,没做多余的判断,如果想增加容错性自己再改改行了。
    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
    */
      

  8.   

    呵呵我就是随便写了一下,意思就是一个UPDATE基本就搞定了。不用游标。
      

  9.   


    这里ID代表某条新闻的ID,有可能临时插入或者删除一条新闻,所以ID不是连续的。