Reputation: 5083
I am importing data from one database to another. The hierarchyid
column must also be ported over with the relationships intact.
If the target table is empty, it's easy. When the target contains rows, the hierarchy as it is in the source table will not be valid in the target table
The easiest would be to increment all values in the hierarchy field with the value of the first ported row's primary key.
So if a source row's hierarchyid
was '/1/12/13/'
and the next available id in target before importing was 101, the hierarchy should change so each value is incremented by 100: '/101/112/113/'
I have read Updating “Hierarchyid” in SQL Server, but do not see how it can be applied to my problem.
How would I go about incrementing each number in each hierarchyid of each row by 1 set value, i.e. increment all numbers in the hierarchy field by 100?
Upvotes: 2
Views: 2744
Reputation: 1
Look at this solution (explanations can be found bellow):
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;
Explanation:
@LastTargetRootNodeAsInteger
) from the target table.a.ID.GetAncestor( a.ID.GetLevel()-1 )
).'/'+...+@LastTargetRootNodeAsInteger+DENSE_RANK()OVER(ORDER BY old_root_node)+'/'
).a.ID.GetReparentedValue(old_root,new_root)
).To see how we get the new IDs, you can execute this query:
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
Results:
Upvotes: 3