【问题标题】:Updating all HierarchyID nodes in SQL Server 2008更新 SQL Server 2008 中的所有 HierarchyID 节点
【发布时间】:2011-09-15 10:02:03
【问题描述】:

我正在将数据从一个数据库导入到另一个数据库。 hierarchyid 列也必须在关系完好无损的情况下被移植。

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

最简单的方法是使用第一个移植行的主键的值递增层次结构字段中的所有值。

因此,如果源行的 hierarchyid'/1/12/13/' 并且在导入之前目标中的下一个可用 id 是 101,则层次结构应该更改,因此每个值都增加 100:'/101/112/113/'

我已阅读Updating “Hierarchyid” in SQL Server,但不知道如何将其应用于我的问题。

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

【问题讨论】:

  • 当您将数据从源表传输到目标表 (1) 时,您始终也会传输第一级或 (2) 在某些情况下您只导入较低级别(例如,您开始从第二级导入数据 => 导入 /101/1/ 而不导入 /101/) ?因此,/101/ 和 /101/1/、/101/2/、.../101/5/、/101/2/1/(第一种情况)或 /101/2/、/101/2/ 1/ ?

标签: sql-server-2008 hierarchyid


【解决方案1】:

看看这个解决方案(可以在下面找到解释):

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. 对于每个旧根节点,我们都会获得一个新根节点 ('/'+...+@LastTargetRootNodeAsInteger+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

结果:

【讨论】:

    猜你喜欢
    • 2011-03-08
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 2010-10-18
    相关资源
    最近更新 更多