none
tree duplizieren mit HierarchyID ... RRS feed

  • Frage

  • Ich habe versucht, nach diesem Beispiel einen Teil eines Baumes zu duplizieren. Funktioniert leider nicht ganz so wie gewünscht, da schlicht der gesamte QUellbaum unter die neue EBene kopiert wird, was schlicht eine Ebene zu viel ist.

    Ich habe in etwa so eine STruktur:

    2015

    Anlage N  Anlage KAP                                             Anlage GSE

                                                                               Q1  Q2   Q3   Q4

    Nun möchte ich eine neuen Eintrag machen '2016'.

    Und dann möchte ich die Baumstruktur unterhalb '2015' kopieren und unterhalb '2016' einfügen.

    Meine Umsetzung führt aber dazu, daß unterhalb '2016' der gesamte Baum '2015' eingefügt wird und nicht nur 'Anlage ...'

    Was mache ich falsch ? Das obige Beispiel ist übrigens das einzige was ich zu diesem Thema gefunden habe. Kaum vorstellbar, daß dieses Problem so selten vorkommen soll.

    USE [DokManagement]
    GO
    /****** Object:  StoredProcedure [dbo].[sp_CopySubtree]    Script Date: 02.06.2018 15:17:40 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- =============================================
    -- Author:		<Author,,Name>
    -- Create date: <Create Date,,>
    -- Description:	<Description,,>
    -- =============================================
    ALTER PROCEDURE [dbo].[sp_CopySubtree] 
    	-- Add the parameters for the stored procedure here
    	@src_folderid_int int,	-- zu kopierender Branch (oder Subtree)
    	@new_parent_id int -- dort einfügen ...
    
    AS
    BEGIN
    	-- SET NOCOUNT ON added to prevent extra result sets from
    	-- interfering with SELECT statements.
    	SET NOCOUNT ON;
    
    	/****** Object:  Table [dbo].[tblKategorien]    Script Date: 25.07.2017 09:58:00 ******/
    	SET ANSI_NULLS ON
    	SET QUOTED_IDENTIFIER ON
    	--SET ANSI_PADDING ON
    	
    	--temporäre Tabelle anlegen
    	CREATE TABLE [dbo].[##temp_tblKategorien](
    		[CatID] int NULL,
    		[CatBezeichnung] [nvarchar](max) NOT NULL, -- Bezeichnung für die Kategorie
    		[CatDescr] [nvarchar](max) NULL, -- ausführliche Beschreibung
    		[CatHierID] [hierarchyid] NOT NULL, 
    		[CatAngelegt] [smalldatetime] NOT NULL CONSTRAINT [DF_Kategorien_CatAngelegt]  DEFAULT (getdate()),
    		[CatLastChanged] [smalldatetime] NULL,
    		[CatParentID] [hierarchyid] NULL,
    		[CatUngueltig] [bit] NOT NULL CONSTRAINT [DF_tblKategorien_CatUngueltig]  DEFAULT ((0)),
    		
    		[CatVisible] [bit] NULL CONSTRAINT [DF_tblKategorien_CatVisible]  DEFAULT ((-1))
    	 
    	) 
    
    	--SET ANSI_PADDING OFF
    	
    	declare @FolderId_hid hierarchyid;
    
    	-- HID des Quell-Baumes bestimmeen
    	select @FolderId_hid = (select CatHierID from dbo.tblKategorien where CatID = @src_folderid_int);
    	
    	INSERT INTO ##temp_tblKategorien (catbezeichnung,CatDescr,Cathierid,CatUngueltig, CatVisible)
    		SELECT CatBezeichnung,CatDescr,CatHierID,CatUngueltig,CatVisible 
    		FROM tblKategorien 
    		Where (CatHierID.IsDescendantOf(@FolderId_hid) = 1) ; --and (CatHierID.GetLevel()>=@FolderId_hid.GetLevel()+1)
    	
    	-- change HID
    	DECLARE @nold hierarchyid, @nnew hierarchyid
    	SELECT @nold = cathierid FROM tblKategorien WHERE catid = @src_folderid_int;
    
    	SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    	BEGIN TRANSACTION
    		-- bestimme den Knoten unter den der neue Branch kopiert werden soll
    		SELECT @nnew = CatHierID FROM tblKategorien WHERE catid = @new_parent_id
    
    		-- jetzt neue Child-HierID erzeugen
    		SELECT @nnew = @nnew.GetDescendant(max(cathierid), NULL) 
    			FROM tblKategorien 
    			WHERE CatHierID.GetAncestor(1) = @nnew ;
    
    		UPDATE ##temp_tblKategorien   
    			SET CatHierID = CatHierID.GetReparentedValue(@nold, @nnew)
    			WHERE CatHierID.IsDescendantOf(@nold) = 1 ;
    
    		INSERT INTO tblKategorien(CatBezeichnung, CatDescr,CatHierID,CatUngueltig,CatVisible)
    			SELECT CatBezeichnung,CatDescr,CatHierID,CatUngueltig, CatVisible 
    			FROM ##temp_tblKategorien;
    
    		drop table ##temp_tblKategorien;
    
    	COMMIT TRANSACTION
    END
    	
    

    Samstag, 2. Juni 2018 13:19

Alle Antworten

  • Hallo NicoNi,

    Und dann möchte ich die Baumstruktur unterhalb '2015' kopieren und unterhalb '2016' einfügen.

    Diese Beschreibung sieht dem Beispiel für die Verschiebung von Angestellten, die schon einem anderen Vorgesetzten unterstellt sind, aus folgendem MSDN-Artikel ähnlich aus:
    Lektion 2.4: Neuanordnen von Daten in einer hierarchischen Tabelle mit hierarchischen Methoden

    Gegebenenfalls hilft auch in Deinem Fall ein Cursor für die Umordnung aller untergeordneten Knoten (child nodes):

    DECLARE children_cursor CURSOR FOR  
    SELECT CatHierID FROM tblKategorien  
    WHERE CatHierID.GetAncestor(1) = @nold;

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Montag, 4. Juni 2018 13:42
    Moderator
  • OKay. Ich werde mir das Beispiel anschauen.

    Die Situation "Angestellte einem  anderen Vorgesetzten zuordnen" findet man im Zusammenhang mit HierarchyID häufiger.

    Überraschenderweise wird selten bis gar nicht auf die Situation "Baumstruktur duplizieren" eingegangen, wohl aber auf "Baumstruktur verschieben"

    Montag, 4. Juni 2018 20:19