Sql Server 2008递归存储过程

时间:2011-03-12 04:35:21

标签: tsql sql-server-2008 stored-procedures recursion

我需要在SQL Server 2008中创建一个存储过程,它将根据某个值更新表。这里的技巧是我需要递归搜索表,直到找到我要查找的值,然后更新当前记录。例如,我有一个包含3列的Employees表:

EMPLOYEEID

经理ID

FAMILYID

对于表中的每个EmployeeId,我想获得它的ManagerId。然后,如果ManagerID!= 0,则转到并获取当前ManagerId的ManagerId(每个ManagerId将指向一个EmployeeId) - 继续执行此操作直到我到达顶级管理器(其中ManagerId == 0)。

找到顶级经理后,我想更新原始记录中的FamilyId列,该记录以上述流程的最后一个EmployeeId的值启动流程。

基本上我需要对表中的每条记录执行此操作。我正在尝试将FamilyId设置为层次结构中所有员工和经理的根管理器的值。

我不确定是否应该使用游标或CTE来完成此操作 - 或者只是在代码中执行此操作。

非常感谢任何帮助。

谢谢!

3 个答案:

答案 0 :(得分:5)

您也可以使用递归CTE。

;WITH Hierarchy
     As (SELECT EmployeeId AS _EmployeeId,
                ManagerId  AS _ManagerId,
                EmployeeId AS _FamilyId
         FROM   @Employee
         WHERE  ManagerId = 0
         UNION ALL
         SELECT e.EmployeeId,
                e.ManagerId,
                h._FamilyId
         FROM   @Employee e
                JOIN Hierarchy h
                  ON h._EmployeeId = e.ManagerId)
UPDATE @Employee
SET    FamilyId = _FamilyId
FROM   Hierarchy h
WHERE  EmployeeId = _EmployeeId  

答案 1 :(得分:2)

这是我第一次尝试它。我希望我明白你的要求。

declare @Employee table (
    EmployeeId int not null 
    , ManagerId int not null
    , FamilyId int null
)

--       1       6
--      / \     / \
--     2   3    7 8
--    / \
--    4 5

insert @Employee values (1, 0, null) 
insert @Employee values (2, 1, null) 
insert @Employee values (3, 1, null) 
insert @Employee values (4, 2, null) 
insert @Employee values (5, 2, null) 
insert @Employee values (6, 0, null) 
insert @Employee values (7, 6, null) 
insert @Employee values (8, 6, null) 

-- the data before the update       
select * from @Employee

-- initial update to get immediate managers
update Employee
set FamilyId = Manager.EmployeeId
from @Employee Employee
inner join @Employee Manager on Manager.EmployeeId = Employee.ManagerId

-- the data after the first update     
select * from @Employee

-- do more updates until done
while exists (
    select * 
    from @Employee 
    where (
        FamilyId is not null 
        and FamilyId not in (
            select EmployeeId from @Employee where ManagerId = 0
        )
    )
) 
begin
    update Employee
    set FamilyId = Manager.ManagerId
    from @Employee Employee
    inner join @Employee Manager on Manager.EmployeeId = Employee.FamilyId
    where (
        Employee.FamilyId is not null 
        and Employee.FamilyId not in (
            select EmployeeId from @Employee where ManagerId = 0
        )
    )
end

-- the data after all updates
select * from @Employee

我确信有更聪明的方法

答案 2 :(得分:0)

我怀疑我会为此调用用户定义的函数(UDF)。 UDF将以递归方式调用自身。

尝试使用google搜索:递归UDF sql server

这个链接似乎给出了一个例子(虽然他们确实注意到从SQL 2000开始,你只能递归32级深度。) http://weblogs.sqlteam.com/jeffs/archive/2003/11/21/588.aspx

很抱歉,我现在没有时间专心致志。如果明天仍然是个问题,我会花更多的时间来解释。