3

DB に hierarchyid データ型を使用するテーブルがあり、親とそのすべての子を新しい親に再割り当てする方法を見つけようとしています。子だけを移動する方法を見つけましたが、親が再割り当てされていません。私のテーブルは次のようになります。

LocationOrg
[OrgNode] [hierarchyid] NOT NULL,
[OrgLevel]  AS ([OrgNode].[GetLevel]()),
[LocationID] [int] NOT NULL,
[LocationName] [varchar](20) NOT NULL

そしていくつかのデータ:

LocationID  | LocationName
__________  |_____________
1           | Headquaters
2           | Location1
3           | Location2
4           | Location3
5           | Location4
6           | Location5
7           | Location6
8           | Location7

現在、Location1 と Location4 が Headquarters の子で、Location2 と Location3 が Location1 の子であり、Location5、Location6、および Location7 が Location2 の子であるように (手動で) セットアップされています。

--Headquaters
  --Location1
    --Location2
    --Location3
  --Location4
    --Location5
    --Location6
    --Location7

親と子を再割り当てするものをどのように書くことができますか? たとえば、Location4 とそのすべての子を Location3 の下に移動したい場合:

--Headquaters
  --Location1
    --Location2
    --Location3
      --Location4
      --Location5
      --Location6
      --Location7

Location4 のすべての子が Location3 の子になっていることに注意してください...親/子構造全体を移動したくありません。それらを新しい親に再割り当てする必要があります。

ここに私がこれまでに得たものがありますが、繰り返しますが、これは子のみを移動し、親は移動しません:

ALTER PROC [dbo].[ReorderLocationOrg]
    @LocationID int,
    @NewParentLocationID int
AS
BEGIN

    DECLARE @OldParent hierarchyid, 
        @NewParent hierarchyid

    SELECT @OldParent = OrgNode 
    FROM LocationOrg
    WHERE LocationID = @LocationID;

    SELECT @NewParent = OrgNode 
    FROM LocationOrg
    WHERE LocationID = @NewParentLocationID;

    DECLARE children_cursor CURSOR FOR
        SELECT OrgNode 
        FROM LocationOrg
        WHERE OrgNode.GetAncestor(1) = @OldParent;

        DECLARE @ChildId hierarchyid;
        OPEN children_cursor
        FETCH NEXT FROM children_cursor INTO @ChildId;
        WHILE @@FETCH_STATUS = 0
        BEGIN
        START:
            DECLARE @NewId hierarchyid;
            SELECT @NewId = @NewParent.GetDescendant(MAX(OrgNode), NULL)
            FROM LocationOrg 
            WHERE OrgNode.GetAncestor(1) = @NewParent;

            UPDATE LocationOrg
            SET OrgNode = OrgNode.GetReparentedValue(@ChildId, @NewId)
            WHERE OrgNode.IsDescendantOf(@ChildId) = 1;
            IF @@error <> 0 GOTO START -- On error, retry
                FETCH NEXT FROM children_cursor INTO @ChildId;

        END
    CLOSE children_cursor;
    DEALLOCATE children_cursor;

    --Move Parent to new node.
    --UPDATE LocationOrg
    --SET OrgNode = @OldParent.GetReparentedValue(@OldParent2, @NewParent)
    --WHERE OrgNode = @OldParent
END

ご覧のとおり (コメントアウトされたセクション)、カーソルの後に親を移動しようとしましたが、重複レコードを挿入できないというエラーがスローされます。

サブツリーの移動に関するこのリンクを見てきましたが、その手順は親と子を構造を維持したまま移動するため、私の場合、Location4 は Location3 の下に移動されますが、Locations 5、6、および 7 は Location4 の子のままです。 3ではありません...これは私が望んでいないことです。

どんな助けでも大歓迎です!

4

2 に答える 2

1

重複エラーは、新しい親ノードの下で既に占有されている位置に oldParent ノードを移動していることが原因である可能性が最も高いです。

これを試して、spの古い親ノードを移動してください(カーソルの後)

--Get a new Hierarchical id for you record
DECLARE @NewOldParentId hierarchyid
SELECT @NewOldParentId = @NewParent.GetDescendant(MAX(OrgNode), NULL)
FROM LocationOrg 
WHERE OrgNode.GetAncestor(1) = @NewParent;

--Give this new id to the oldParent
UPDATE LocationOrg
SET OrgNode = @NewOldParentId
WHERE LocationID = @LocationID;
于 2013-06-10T13:23:18.397 に答える