이 솔루션에서 봐 (설명이 울부 짖는 소리 찾을 수 있습니다) :
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)
)를 얻습니다.
- 모든 오래된 루트 노드에 대해 우리는 새로운 루트 노드 (
'/'[email protected]+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
결과 :
당신이 테이블을 대상으로 소스 테이블에서 데이터를 전송 (1 (예 : 두 번째 수준에서 데이터를 가져 오기 시작 => 가져 오기/101/1/가져 오기/101/가져 오기없이 데이터를 가져 오기 시작))?/101/2 /, .../101/2 /,/101/2/1/(첫 번째 경우) 또는/101/2 /,/101/2/1/ ? –