2011-09-15 47 views
2

我正在将数据从一个数据库导入到另一个数据库。 hierarchyid列也必须完整地移植到关系中。更新SQL Server 2008中的所有HierarchyID节点

如果目标表为空,则很容易。当目标包含行时,源表中的层次结构在目标表中无效

最简单的方法是使用第一个带端口行的主键的值增加层次结构字段中的所有值。

所以,如果一个源行的hierarchyid'/1/12/13/'和目标进口是101之前的下一个可用的ID,层次结构应该改变,因此每个值增加100:'/101/112/113/'

我已阅读Updating “Hierarchyid” in SQL Server,但看不到它如何应用于我的问题。

我将如何去增加每行的每个hierarchyid中的每个数字一个设置值,即将层次结构中的所有数字增加100?

+0

当您从源表传输数据到目标表(1 ),那么你总是转移第一级别,或者(2)有些情况下,只导入次级别(例如,你开始从第二级导入数据=>你导入/ 101/1 /不导入/ 101/)?因此,/ 101 /和/ 101/1 /,/ 101/2 /,....../101/5 /,/ 101/2/1 /(第一种情况)或/ 101/2 /,/ 101/2/1 /? –

回答

3

看这个溶液(解释可以波纹管找到):

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; 

说明:

  1. 假设找到从目标表中最后一个根节点(@LastTargetRootNodeAsInteger)第一步。
  2. 然后,对于来自源表的每个ID,我们得到根节点(旧根节点:a.ID.GetAncestor(a.ID.GetLevel()-1))。
  3. 对于每个旧的根节点,我们得到新的根节点('/'[email protected]+DENSE_RANK()OVER(ORDER BY old_root_node)+'/')。
  4. 最后,我们将插入具有新根节点的行(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 

结果:

results