このソリューションを見(説明は怒鳴る見つけることができます):
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 )あなたは常に最初のレベルを転送するか、または(2)下位レベルのみをインポートする場合(たとえば、2番目のレベルからデータをインポートする=>インポートする/ 101/1 /インポートしないで101/)?/101/2 /、/ 101/2 /、/ 101/2/1 /(第1の場合)、/ 101/2 /、/ 101/2/1 /π –