Подтвердить что ты не робот

Иерархический идентификатор SQL 2008 с несколькими корневыми узлами

Я хотел использовать новый тип HierarchyID в SQL Server 2008 для обработки отношений страниц в небольшом вики-приложении. Однако для этого необходимо иметь несколько корневых узлов, поскольку каждая основная статья/страница для каждой учетной записи будет иметь корневой каталог node.

Из того, что я прочитал, тип HierarchyID разрешает только 1 корень node за столбец, это правильно? и есть ли способ включить несколько корневых узлов?

4b9b3361

Ответ 1

Да, вы правильно читаете - с помощью HierarchyID допускается только один корень node. Это так, как мне кажется, и не существует, насколько мне известно, возможности внедрить искусственный новый "ubber-root", который не имеет никакой другой цели, кроме как позволить вам иметь несколько подкорней первого уровня....

Марк

Ответ 2

Я проводил некоторое тестирование, и кажется, что вам не нужна запись с корневой иерархией.

Например, обычно вы бы использовали один root node (уровень 1) и несколько дочерних, но вы можете пропустить root node, не имея корневых записей, только записи, начинающиеся с уровня 2:

//table schema
CREATE TABLE [Entity](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL
    [Hierarchy] [hierarchyid] NOT NULL,
 CONSTRAINT [PK_Entity] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

//Insert first 'root', which is technicall a child without a parent
INSERT INTO [Entity]
           ([Name]
           ,[Description]
           ,[Hierarchy])
     VALUES
           ('Root A'
           ,hierarchyid::GetRoot().GetDescendant(NULL,NULL))


//Create the second 'root'
INSERT INTO [Entity]
           ([Name]
           ,[Hierarchy])
     VALUES
           ('Root B'
           ,hierarchyid::GetRoot().GetDescendant((select MAX(hierarchy) from entity where hierarchy.GetAncestor(1) = hierarchyid::GetRoot()),NULL))

Теперь, если вы выберете все строки из таблицы, вы увидите:

SELECT [ID]
      ,[Name]
      ,[Hierarchy],
       [Hierarchy].ToString()
  FROM [Entity]

ID           Иерархия       1                        /n/1/
2                        /2/

Я не уверен, если бы это было рекомендовано, но концептуально это позволяет вам иметь несколько корней, если вы считаете 2-й уровень в дереве корневым

Ответ 3

Что я делаю, чтобы создавать уникальные корневые узлы, просто нарисуйте свою таблицу PrimaryKey как HierarchyId на нужные записи привязки, например.

Учитывая притворную таблицу, имеющую ItemID | ArticleID_Parent | Иерархия, вы можете настроить все "корни", чтобы стать таким уникальным:

UPDATE [Article]
SET Hierarchy=CAST('/'+CAST([ArticleID] as varchar(30))+'/' AS hierarchyid)
WHERE [ArticleID_Parent]=0

.. затем получить "ветвь" определенного корня,

SELECT * FROM [Article]
WHERE Article.Hierarchy.IsDescendantOf((SELECT Hierarchy FROM Article WHERE ArticleID=XXXX)) = 1 

Ответ 4

Тип данных иерархии, который может использоваться для представления позиции в иерархии. Тем не менее, он по сути не применяет иерархию. Это выдержка из документации MSDN для hierarchyid.

Приложение может создавать и присваивать значения иерархии таким образом, чтобы желаемое соотношение между строками отражалось в значениях.

Этот пример показывает, как комбинация вычисленного столбца и внешнего ключа может использоваться для принудительного использования дерева.

CREATE TABLE Org_T3
(
   EmployeeId hierarchyid PRIMARY KEY,
   ParentId AS EmployeeId.GetAncestor(1) PERSISTED  
      REFERENCES Org_T3(EmployeeId),
   LastChild hierarchyid, 
   EmployeeName nvarchar(50)
)
GO

В вашем случае вы должны изменить формулу вычисленного столбца, чтобы для корневых записей Null (внешние ключи не применялись для значений Null в SQL Server) или, возможно, немодифицированный иерархия записи (корни были бы их собственными родителями) будет возвращен.

Это упрощенная версия приведенного выше примера, которая идет со стратегией назначения корневых узлов null ParentId.

create table Node
(
    Id hierarchyid primary key,
    ParentId AS case when Id.GetLevel() = 1 then 
                    Null 
                else 
                    Id.GetAncestor(1) 
                end PERSISTED REFERENCES Node(Id),
    check (Id.GetLevel() != 0)
)

insert into Node (Id) values ('/1/');
insert into Node (Id) values ('/1/1/');
insert into Node (Id) values ('/'); --Fails as the roots will be at level 1.
insert into Node (Id) values ('/2/1/'); --Fails because the parent does not exist.

select Id.ToString(), ParentId.ToString() from Node;

Удаляются только действительные вставки сверху.

Id ParentId

/1/NULL

/1/1//1/

Ответ 5

У вас не может быть один, "не отображаемый" корень и все основные статьи на уровне 1?