Itzik Ben-Gan 在此描述了一些如何使用 HierarchyId 数据类型的简单方法。
http://sqlmag.com/t-sql/hierarchyid
他使用存储过程将子进程添加到某个根目录
-- Web Listing 2: Script to Create Stored Procedure usp_AddEmp
IF OBJECT_ID('dbo.usp_AddEmp', 'P') IS NOT NULL
DROP PROC dbo.usp_AddEmp;
GO
CREATE PROC dbo.usp_AddEmp
@empid AS INT,
@mgrid AS INT = NULL,
@empname AS VARCHAR(25),
@salary AS MONEY
AS
DECLARE
@hid AS HIERARCHYID,
@mgr_hid AS HIERARCHYID,
@last_child_hid AS HIERARCHYID;
IF @mgrid IS NULL
SET @hid = HIERARCHYID::GetRoot();
ELSE
BEGIN
SET @mgr_hid = (SELECT hid FROM dbo.Employees WHERE empid = @mgrid);
SET @last_child_hid =
(SELECT MAX(hid) FROM dbo.Employees
WHERE hid.GetAncestor(1) = @mgr_hid);
SET @hid = @mgr_hid.GetDescendant(@last_child_hid, NULL);
END
INSERT INTO dbo.Employees(empid, hid, empname, salary)
VALUES(@empid, @hid, @empname, @salary);
GO
要向树添加任何叶子,需要像这样调用此过程:
EXEC dbo.usp_AddEmp
@empid = 1, @mgrid = NULL, @empname = 'David' , @salary = $10000.00;
EXEC dbo.usp_AddEmp
@empid = 2, @mgrid = 1, @empname = 'Eitan' , @salary = $7000.00;
EXEC dbo.usp_AddEmp
@empid = 3, @mgrid = 1, @empname = 'Ina' , @salary = $7500.00;
EXEC dbo.usp_AddEmp
@empid = 4, @mgrid = 2, @empname = 'Seraph' , @salary = $5000.00;
EXEC dbo.usp_AddEmp
@empid = 5, @mgrid = 2, @empname = 'Jiru' , @salary = $5500.00;
EXEC dbo.usp_AddEmp
@empid = 6, @mgrid = 2, @empname = 'Steve' , @salary = $4500.00;
EXEC dbo.usp_AddEmp
@empid = 7, @mgrid = 3, @empname = 'Aaron' , @salary = $5000.00;
EXEC dbo.usp_AddEmp
@empid = 8, @mgrid = 5, @empname = 'Lilach' , @salary = $3500.00;
EXEC dbo.usp_AddEmp
@empid = 9, @mgrid = 7, @empname = 'Rita' , @salary = $3000.00;
EXEC dbo.usp_AddEmp
@empid = 10, @mgrid = 5, @empname = 'Sean' , @salary = $3000.00;
EXEC dbo.usp_AddEmp
@empid = 11, @mgrid = 7, @empname = 'Gabriel', @salary = $3000.00;
EXEC dbo.usp_AddEmp
@empid = 12, @mgrid = 9, @empname = 'Emilia' , @salary = $2000.00;
EXEC dbo.usp_AddEmp
@empid = 13, @mgrid = 9, @empname = 'Michael', @salary = $2000.00;
EXEC dbo.usp_AddEmp
@empid = 14, @mgrid = 9, @empname = 'Didi' , @salary = $1500.00;
我的问题是:
我有一张表,其中包含叶子兄弟列表,我需要将其添加到同一级别的父级 14 中
declare @toadd table
(
empid INT,
mgrid INT,
empname VARCHAR(25),
salary MONEY
)
insert into @toadd(empid, mgrid, empname, salary)
select 15, 14, 'Itzik', $0.01
union all
select 16, 14, 'Jack', $0.02
union all
select 17, 14, 'Alex', $0.03
union all
select 18, 14, 'Mary', $0.04
union all
select 19, 14, 'John', $0.05
我可以创建游标并调用该过程 N 次。 但也许可以做得更有效?不知何故在一个查询中?
您可以使用“/[int/][…n]”形式的字符串将正确转换为 HierarchyId 的事实。因此,不要使用 GetDescendant 向经理添加下属,而是获取经理的 HierarchyId,对其调用 ToString(),在其上附加“{EmpId}/”,然后将其转换回 HierarchyId(或者如果具体来说:
列已经是这种类型。with emps_and_mgrs as (
select *, m.hid as mhid
from @toadd as t
cross apply (
select hid
from dbo.Employees
where empid= t.mgrid
) as m
)
INSERT INTO dbo.Employees(empid, hid, empname, salary)
select empid, mhid.ToString() + cast(empid as varchar) + '/', empname, salary
from emps_and_mgrs;
这假设每个人的 hid 值的形式为“{manager's hid}/empid/”。这包括原始示例中的 David;他的值不是 GetRoot()(即“/”),而是“/1/”。另外值得注意的是,如果您打算采用此策略,我还将经理的 empid 存储在行中。这样,您可以编写一个递归 cte,仅使用 empid 和经理的 empid 在出现问题时重新生成所有 HierarchyId。