2011-09-15 4 views
2

한 데이터베이스에서 다른 데이터베이스로 데이터를 가져옵니다. hierarchyid 열은 관계가 변경되지 않은 상태로 이식되어야합니다.SQL Server 2008의 모든 HierarchyID 노드 업데이트

대상 테이블이 비어 있으면 쉽습니다. 대상에 행이 포함되어 있으면 원본 테이블의 계층 구조가 대상 테이블에서 유효하지 않습니다.

가장 쉽게 계층 구조 필드의 모든 값을 첫 번째 포팅 된 행의 기본 키 값으로 증가시킵니다.

소스 행의 hierarchyid'/1/12/13/' 101이었다 가져 오기 전에 대상에 추가로 사용이 가능한 ID 있다면

그래서, 계층 구조는 각각의 값이 100만큼 증가 변경해야합니다 : '/101/112/113/'

나는 Updating “Hierarchyid” in SQL Server을 읽고,하지만 표시되지 않습니다 그것이 내 문제에 어떻게 적용될 수 있는지.

각 행의 각 hierarchyid의 각 값을 1 설정 값만큼 증가시키는 방법, 즉 계층 구조 필드의 모든 숫자를 100 씩 증가시키는 방법은 무엇입니까?

+0

당신이 테이블을 대상으로 소스 테이블에서 데이터를 전송 (1 (예 : 두 번째 수준에서 데이터를 가져 오기 시작 => 가져 오기/101/1/가져 오기/101/가져 오기없이 데이터를 가져 오기 시작))?/101/2 /, .../101/2 /,/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; 

설명 : 대상 테이블에서 마지막 루트 노드 (@LastTargetRootNodeAsInteger를) 찾을 가정

  1. 첫 번째 단계.
  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