初始表:a        b          c        d
------------------------------------
1 0001
2 1        0002
5        1        0003
6 2 0004
8 5 0005
9 8 0006 更新设置后:a        b          c        d
------------------------------------
1 0001 0001
2 1 0002 0001
5        1        0003     0001
6 2 0004 0001
8 4 0005 0005
9 8 0006 0005

解决方案 »

  1.   

    DECLARE @t TABLE(a int, b int, c char(4), d char(4))
    INSERT @t(a, b, c)
    SELECT 1, NULL, '0001' UNION ALL
    SELECT 2, 1, '0002' UNION ALL
    SELECT 5, 1, '0003' UNION ALL
    SELECT 6, 2, '0004' UNION ALL
    SELECT 8, 4, '0005' UNION ALL
    SELECT 9, 8, '0006'-- 更新
    UPDATE A SET 
    d = c
    FROM @t A
    WHERE b IS NULL 
    OR NOT EXISTS(
    SELECT * FROM @t
    WHERE a = A.b)
    WHILE @@ROWCOUNT > 0
    UPDATE A SET 
    d = B.d
    FROM @t A, @t B
    WHERE A.d IS NULL
    AND B.d IS NOT NULL
    AND A.b = B.a
    SELECT * FROM @t-- 结果:
    a           b           c    d
    ----------- ----------- ---- ----
    1           NULL        0001 0001
    2           1           0002 0001
    5           1           0003 0001
    6           2           0004 0001
    8           4           0005 0005
    9           8           0006 0005(6 行受影响)
      

  2.   

    楼主的例子数据初始表的a = 8这行的b应该等于4,而不是5.
    if object_id('tbTest') is not null
          drop table tbTest
    GO
    ----创建测试数据
    create table tbTest(a int,b int,c varchar(10),d varchar(10))
    insert tbTest(a,b,c)
    select 1,NULL,'0001' union all
    select 2,1,   '0002' union all
    select 5,1,   '0003' union all
    select 6,2,   '0004' union all
    select 8,4,   '0005' union all     /*此行b应为4,而不是5*/
    select 9,8,   '0006'
    GO
    if object_id('fnFindRoot') is not null
          drop function fnFindRoot
    GO
    ----创建查找层次的函数,参数为a列值,返回值为根节点的a列值
    create function fnFindRoot(@id int)
    returns int
    as
    begin
            declare @pid int
            select @pid = b from tbTest where a = @id
            while @@rowcount > 0
                select @pid = b from tbTest where a = @pid  
        select @pid = a from tbTest where isnull(b,0) = isnull(@pid,0)  
        return @pid       /*返回根节点的ID*/
    end
    GO
    ----更新
    update t set d = (select c from tbTest where a = (select dbo.fnFindRoot(t.a)))
    from tbTest t
    ----查看
    select * from tbTest----清除测试环境
    drop table tbTest
    drop function fnFindRoot/*结果
    a   b    c    d
    ---------------------------------------
    1 NULL 0001 0001
    2 1 0002 0001
    5 1 0003 0001
    6 2 0004 0001
    8 4 0005 0005
    9 8 0006 0005
    */