看看这个解决方案(可以在下面找到解释):
DECLARE @Source TABLE
(
ID HIERARCHYID PRIMARY KEY
,Name NVARCHAR(50) NOT NULL
);
DECLARE @Target TABLE
(
ID HIERARCHYID PRIMARY KEY
,Name NVARCHAR(50) NOT NULL
,OldID HIERARCHYID
);
INSERT @Source
VALUES
('/1/','a'), ('/1/1/','aa'), ('/1/2/','ab'), ('/1/3/','ac')
,('/2/','b')
,('/3/','c'), ('/3/3/','cc')
,('/4/','d'), ('/4/1/','da'), ('/4/2/','db'), ('/4/2/1/','dba'), ('/4/2/1/5/','dbaf');
DECLARE @LastTargetRootNodeAsInteger INT;
SELECT @LastTargetRootNodeAsInteger = REPLACE( MAX( a.ID.GetAncestor( a.ID.GetLevel()-1 ) ).ToString(), '/', '')
FROM @Target a;
WITH CteUpdate
AS
(
SELECT a.ID
,a.Name
,a.ID.GetAncestor( a.ID.GetLevel()-1 ) AS OldRootID
,CONVERT(HIERARCHYID,'/'+CONVERT(VARCHAR(256),@LastTargetRootNodeAsInteger+DENSE_RANK()OVER(ORDER BY a.ID.GetAncestor( a.ID.GetLevel()-1 )))+'/') NewRootID
FROM @Source a
)
INSERT @Target(ID, Name, OldID)
SELECT a.ID.GetReparentedValue(a.OldRootID, a.NewRootID), a.Name, a.ID
FROM CteUpdate a;
SELECT *
,t.ID.ToString() AS CurrentNodeToString
,t.OldID.ToString() AS OldNodeToString
FROM @Target t
ORDER BY t.ID;
解释:
@LastTargetRootNodeAsInteger
第一步假设从目标表中找到最后一个根节点 ( )。
- 然后,对于源表中的每个 ID,我们得到根节点(旧根节点:)
a.ID.GetAncestor( a.ID.GetLevel()-1 )
。
- 对于每个旧的根节点,我们都会得到新的根节点 (
'/'+...+@LastTargetRootNodeAsInteger+DENSE_RANK()OVER(ORDER BY old_root_node)+'/'
)。
- 最后,我们将插入带有新根节点 (
a.ID.GetReparentedValue(old_root,new_root)
) 的行。
要查看我们如何获取新 ID,您可以执行以下查询:
SELECT *
,c.ID.GetReparentedValue(c.OldRootNode,c.NewRootNode).ToString() AS NewCurrentNode
FROM
(
SELECT *
,'/'+CONVERT(VARCHAR(256),@LastTargetRootNodeAsInteger+DENSE_RANK() OVER(ORDER BY b.OldRootNode))+'/' AS NewRootNode
FROM
(
SELECT *
,a.ID.ToString() AS OldCurrentNode
,a.ID.GetAncestor( a.ID.GetLevel()-1 ).ToString() AS OldRootNode
FROM @Source a
) b
) c
结果: