Обновить SQL Server HierarchyId после триггера вставки - PullRequest
3 голосов
/ 30 декабря 2011

Я разрабатываю центр сообщений в информационной системе, и сегодня пользователь Эрик предложил использовать тип данных иерархии для отслеживания ответа на сообщение, поскольку цель состоит в том, чтобы отобразить его в виде беседы в Outlook или Gmail.

Чтобы упростить, в моей базе данных есть таблица Сообщений:

MessageId int PK
ReplyToId int FK null
Subject varchar
Body varchar
Hierarchy hierarchyid

Когда вставляется новое сообщение, у меня есть триггер для обновления.

Я вставил новое сообщение, и иерархия пуста, потому что это первое сообщение, а не ответ.

Если попытаться вставить ответ на это сообщение, иерархия по-прежнему равна нулю ...: (

Мой триггер:

ALTER TRIGGER [dbo].[trg_UpdateHierarchy] 
   ON  [dbo].[Messages]
   AFTER INSERT
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for trigger here

    DECLARE @replyId int
    SELECT @replyId = inserted.ReplyId
    FROM inserted
    IF(@replyId IS NULL)
    BEGIN
        RETURN
    END

    DECLARE @parent hierarchyid
    SELECT @parent = Hierarchy
    FROM   [Messages]
    WHERE  [Messages].MessageId = @replyId


    DECLARE @currentHierarchy hierarchyid = @parent.GetDescendant(null, null).ToString()
    DECLARE @messageId int
    SELECT @messageId = inserted.MessageId
        FROM inserted
    UPDATE [Messages]
        SET Hierarchy = @currentHierarchy
        WHERE [Messages].MessageId = @messageId
END
GO 

Что я делаю не так?

Еще один момент, который я читал об индексе, но глубина в первую очередь не подходит, потому что многие из них имеют значение NULL, потому что первое сообщение из диалога имеет значение NULL, а «хлеб первым» является лучшим типом индекса для имеет лучшую производительность? Или я могу отказаться от этого индекса?

Заранее спасибо!

EDIT:

Я обновил триггер, но не делаю hierarchyid правильно.

Теперь триггер:

ALTER TRIGGER [dbo].[trg_UpdateHierarchy] 
   ON  [dbo].[Messages]
   AFTER INSERT
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for trigger here
    DECLARE @messageId int
    DECLARE @ParentId int
    SELECT  @messageId = inserted.MessageId,
            @ParentId = inserted.ParentId
        FROM inserted

    IF(@ParentId IS NULL)
        BEGIN
            UPDATE [Messages]
                SET Hierarchy = hierarchyid::GetRoot()
                WHERE [Messages].MessageId = @messageId
            RETURN
        END
    ELSE
        BEGIN
            DECLARE @parent hierarchyid
            SELECT @parent = Hierarchy
                FROM   [Messages]
                WHERE  [Messages].MessageId = @ParentId

            DECLARE @lastHierarchy hierarchyid
            SELECT @lastHierarchy = MAX(Hierarchy) 
                FROM [Messages] 
                WHERE Hierarchy.GetAncestor(1) = @parent

            UPDATE [Messages]
                SET Hierarchy = @parent.GetDescendant(@lastHierarchy, NULL)
                WHERE [Messages].MessageId = @messageId
        END
END  

Если я вставляю сообщения типа id = 2 имеет parentId = 1, а id = 3 имеет parentId = 2, имеют следующую иерархию:
id = 1, hierarchy = \<br> id = 2, hierarchy = \1\<br> id = 3, hierarchy = \1\1\

Первая и вторая запись имеют правильную иерархию, но следующая нет ...: (

Есть подсказка?

1 Ответ

1 голос
/ 03 ноября 2012

На самом деле является одной правильной реализацией иерархии. Тем не менее, у него есть ограничения для пакетных вставок, но это еще одна проблема ... также, возможно, имеет смысл начать все "корни" с \x или на один уровень глубины, чтобы разговоры не разделялись родительское дерево.

В любом случае вставьте второй узел с id = 4, parentId = 2, тогда он должен выглядеть как hierarchy = \1\2 (он находится на том же уровне иерархии, но после \1\1).

Значения, показанные в hierarchy «строковой» форме , не должны относиться к значению parentId!

...