Как переместить поддерево иерархии, если у нового родителя уже есть дети? - PullRequest
0 голосов
/ 07 апреля 2020

Полагаю, проблема хорошо описана в заголовке. У меня есть такая таблица:

CREATE TABLE [Employees] (
[Id] INT identity(1, 1) PRIMARY KEY
,[Hid] HIERARCHYID NOT NULL
,[Name] VARCHAR(50) NULL
,[Secondname] VARCHAR(50)
,[Surname] VARCHAR(50)
,[BossId] INT FOREIGN KEY REFERENCES [Employees]([Id])
,[PositionId] INT FOREIGN KEY REFERENCES [Positions]([Id])
,[DepartmentId] INT FOREIGN KEY REFERENCES [Departments]([Id])
,[RecruitDate] DATE NOT NULL
);

И мне нужно сменить начальника сотрудника с одного на другого. Очевидно, есть хорошее решение - GetReparentedValue () , и я использовал этот пример, который, казалось, был именно тем, что мне было нужно. Но это решение не работает. Hid.GetAncestor (1) соответствует предыдущему BossHid. Возможно, проблема в том, что это не может работать хорошо, если у нового родителя уже есть дети. Это действительно расстраивает меня. Значит ли это, что мне нужно писать рекурсивный CTE самостоятельно? Вот код, который должен был работать, но он не работал:

    CREATE PROCEDURE UpdateEmployee @Id INT
    ,@Name VARCHAR(50)
    ,@Secondname VARCHAR(50)
    ,@Surname VARCHAR(50)
    ,@BossId INT
    ,@PosId INT
    ,@DepId INT
    ,@Rdate DATE
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @BossExist INT
        ,@OldBossHid HIERARCHYID
        ,@NewBossHid HIERARCHYID
        ,@LastHid HIERARCHYID;

    SELECT @BossExist = count(*)
    FROM dbo.Employees
    WHERE [Hid] = HIERARCHYID::GetRoot();

    IF @BossExist != 0
        AND @BossId IS NULL
        RETURN;

    SELECT @OldBossHid = (
            SELECT [Hid].GetAncestor(1)
            FROM dbo.Employees
            WHERE @Id = [Id]
            );

    SELECT @NewBossHid = (
            SELECT [Hid].GetAncestor(1)
            FROM dbo.Employees
            WHERE @BossId = BossId
            );

    SELECT @LastHid = @NewBossHid.GetDescendant(MAX([Hid]), NULL)
    FROM dbo.Employees
    WHERE [Hid].GetAncestor(1) = @NewBossHid;

    UPDATE dbo.Employees
    SET [Hid] = [Hid].GetReparentedValue(@OldBossHid, @NewBossHid)
    WHERE [Hid].IsDescendantOf(@OldBossHid) = 1;

    UPDATE dbo.Employees
    SET [Name] = @Name
        ,[Secondname] = @Secondname
        ,[Surname] = @Surname
        ,[BossId] = @BossId
        ,[PositionId] = @PosId
        ,[DepartmentId] = @DepId
        ,[RecruitDate] = @Rdate
    WHERE @Id = Id;
END
GO

Спасибо.

...