Udostępnij za pośrednictwem


Working with hierarchyid Data

Ten temat zawiera informacje o typowych działań wykonywanych w zarządzaniu i badanie drzewa hierarchicznego danych.

W tym temacie.

Zarządzanie hierarchyid z za pomocą drzewa

Wymuszanie na drzewie

Przykład przy użyciu środowiska CLR

Przenoszenie poddrzewa

Zarządzanie hierarchyid z za pomocą drzewa

Chociaż hierarchyid kolumna nie reprezentuje drzewo, aplikacji mogą łatwo upewnij się, że obsługuje.

  • Podczas generowania nowych wartości, wykonaj jedną z następujących czynności:

    • Przechowywania informacji o ostatnim podrzędność numer wiersza nadrzędnego.

    • Obliczyć ostatni element podrzędność.W ten sposób efektywnie wymaga indeksu pierwszego szerokość.

  • Wymusić unikatowość przez utworzenie indeks unikatowy dla kolumna, prawdopodobnie jako część klucz klastrowania.Aby upewnić się, są wstawiane unikatowych wartości, wykonaj jedną z następujących czynności:

    • Określania unikatowość każdego nowego węzła podrzędnego i wstaw go, w ramach transakcji możliwy do serializacji.

    • wykrywać awarii naruszenie unikatowego klucz i spróbuj ponownie.

Przykład za pomocą wykrywania błędów

W poniższym przykładzie przykładowy kod oblicza nowe podrzędność EmployeeId wartość, a następnie wykrywa naruszenia klucz i powraca do INS_EMP znacznik, aby Przelicz EmployeeId wartość dla nowego wiersza:

USE AdventureWorks ;
GO

CREATE TABLE Org_T1
   (
    EmployeeId hierarchyid PRIMARY KEY,
    OrgLevel AS EmployeeId.GetLevel(),
    EmployeeName nvarchar(50) 
   ) ;
GO

CREATE INDEX Org_BreadthFirst ON Org_T1(OrgLevel, EmployeeId)
GO

CREATE PROCEDURE AddEmp(@mgrid hierarchyid, @EmpName nvarchar(50) ) 
AS
BEGIN
    DECLARE @last_child hierarchyid
INS_EMP: 
    SELECT @last_child = MAX(EmployeeId) FROM Org_T1 
    WHERE EmployeeId.GetAncestor(1) = @mgrid
INSERT Org_T1 (EmployeeId, EmployeeName)
SELECT @mgrid.GetDescendant(@last_child, NULL), @EmpName 
-- On error, return to INS_EMP to recompute @last_child
IF @@error <> 0 GOTO INS_EMP 
END ;
GO

Przykład za pomocą możliwy do serializacji transakcji

The Org_BreadthFirst index insures determining @last_child is a zakres seek.Oprócz innych przypadkach błąd aplikacji może być sprawdzenie duplikatów naruszenie klucz po insert wskazuje próba dodania wielu pracowników o tym samym identyfikatorze i w związku z tym @ last_child musi być przeliczane.W poniższym kodzie użyto możliwy do serializacji transakcji i indeksu pierwszego szerokość do obliczenia nowej wartości węzła:

CREATE TABLE Org_T2
    (
    EmployeeId hierarchyid PRIMARY KEY,
    LastChild hierarchyid, 
    EmployeeName nvarchar(50) 
    ) ;
GO

CREATE PROCEDURE AddEmp(@mgrid hierarchyid, @EmpName nvarchar(50)) 
AS
BEGIN
DECLARE @last_child hierarchyid
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION 

UPDATE Org_T2 
SET @last_child = LastChild = EmployeeId.GetDescendant(LastChild,NULL)
WHERE EmployeeId = @mgrid
INSERT Org_T2 (EmployeeId, EmployeeName) 
    VALUES(@last_child, @EmpName)
COMMIT
END ;

Poniższy kod wypełnia tabela z trzech wierszy i zwraca wyniki:

INSERT Org_T2 (EmployeeId, EmployeeName) 
    VALUES(hierarchyid::GetRoot(), 'David') ;
GO
AddEmp 0x , 'Sariya'
GO
AddEmp 0x58 , 'Mary'
GO
SELECT * FROM Org_T2

Here is the result set.

EmployeeId LastChild EmployeeName
---------- --------- ------------
0x        0x58       David
0x58      0x5AC0     Sariya
0x5AC0    NULL       Mary

Arrow icon used with Back to Top linkPowrót do początku

Wymuszanie na drzewie

Powyższe przykłady ilustrują, w jaki sposób aplikacji mogą zapewnić drzewa jest przechowywana.Aby wymusić drzewa, za pomocą ograniczeń, kolumna obliczana, definiujący nadrzędnego dla każdego węzła mogą być tworzone za pomocą ograniczenia na klucz obcy do identyfikatora klucz podstawowy.

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

Wymuszanie relacja ta metoda jest preferowana, jeżeli kod, który nie jest zaufany, aby zachować hierarchiczną drzewa ma bezpośredni dostęp DML do tabela.Ta metoda może zmniejszyć wydajność, ponieważ ograniczenia, należy sprawdzić w każdej operacji DML.

Arrow icon used with Back to Top linkPowrót do początku

Przykład przy użyciu środowiska CLR

Znajdowanie najmniejszej wspólnej element nadrzędny jest typowych operacji związanych z dwóch węzłów w hierarchii.Może to być zapisany przy użyciu jednego Transact-SQL lub CLR, ponieważ hierarchyid Typ jest dostępny w obu. Środowisko CLR jest zalecane, ponieważ wydajność będzie szybsze.

Aby znaleźć listę obiektów nadrzędnych i znajdowanie najmniejszej wspólnej element nadrzędny, należy użyć następującego kodu CLR:

using System;
using System.Collections;
using System.Text;
using Microsoft.SqlServer.Server;
using Microsoft.SqlServer.Types;

public partial class HierarchyId_Operations
{
    [SqlFunction(FillRowMethodName = "FillRow_ListAncestors")]
    public static IEnumerable ListAncestors(SqlHierarchyId h)
    {
        while (!h.IsNull)
        {
            yield return (h);
            h = h.GetAncestor(1);
        }
    }
    public static void FillRow_ListAncestors(Object obj, out SqlHierarchyId ancestor)
    {
        ancestor = (SqlHierarchyId)obj;
    }

    public static HierarchyId CommonAncestor(SqlHierarchyId h1, HierarchyId h2)
    {
        while (!h1.IsDescendant(h2))
            h1 = h1.GetAncestor(1);
        
        return h1;
    }
}

Aby użyć ListAncestor and CommonAncestor następujące metodTransact-SQL przykłady, tworzyć biblioteki i utworzyć HierarchyId_Operations wirtualny plik dziennika w SQL Server przez wykonaniem kodu, podobny do następującego:

CREATE ASSEMBLY HierarchyId_Operations 
FROM '<path to DLL>\ListAncestors.dll'
GO

Arrow icon used with Back to Top linkPowrót do początku

Wyświetlanie listy obiekty nadrzędne

Tworzenie listy obiektów nadrzędnych węzła jest typowych operacji dla wystąpienie do wyświetlania pozycji w organizacji.Jednym ze sposobów robić to za pomocą-wycenione funkcja tabela przy użyciu HierarchyId_Operations klasy zdefiniowanej powyżej:

Za pomocą Transact-SQL:

CREATE FUNCTION ListAncestors (@node hierarchyid)
RETURNS TABLE (node hierarchyid)
AS
EXTERNAL NAME HierarchyId_Operations.HierarchyId_Operations.ListAncestors
GO

Przykład użycia:

DECLARE @h hierarchyid
SELECT @h = OrgNode 
FROM HumanResources.EmployeeDemo  
WHERE LoginID = 'adventure-works\janice0' -- /1/1/5/2/

SELECT LoginID, OrgNode.ToString() AS LogicalNode
FROM HumanResources.EmployeeDemo AS ED
JOIN ListAncestors(@h) AS A 
   ON ED.OrgNode = A.Node
GO

Znajdowanie najniższy wspólny element nadrzędny

Za pomocą HierarchyId_Operations klasy zdefiniowanej powyżej, utwórz następujące Transact-SQL funkcja Wyszukiwanie najniższy wspólny element nadrzędny obejmujące dwa węzły w hierarchii:

CREATE FUNCTION CommonAncestor (@node1 hierarchyid, @node2 hierarchyid)
RETURNS hierarchyid
AS
EXTERNAL NAME HierarchyId_Operations.HierarchyId_Operations.CommonAncestor
GO

Przykład użycia:

DECLARE @h1 hierarchyid, @h2 hierarchyid

SELECT @h1 = OrgNode 
FROM  HumanResources.EmployeeDemo 
WHERE LoginID = 'adventure-works\jossef0' -- Node is /1/1/3/

SELECT @h2 = OrgNode 
FROM HumanResources.EmployeeDemo  
WHERE LoginID = 'adventure-works\janice0' -- Node is /1/1/5/2/

SELECT OrgNode.ToString() AS LogicalNode, LoginID 
FROM HumanResources.EmployeeDemo  
WHERE OrgNode = dbo.CommonAncestor(@h1, @h2) ;

Wynikowy węzeł jest/1/1 /

Arrow icon used with Back to Top linkPowrót do początku

Przenoszenie poddrzewa

Inna operacja wspólne jest przeniesienie poddrzewa.Poniższa procedura ma poddrzewa z @ oldMgr i czyni go (w tym @ oldMgr) poddrzewa**@ newMgr**.

CREATE PROCEDURE MoveOrg(@oldMgr nvarchar(256), @newMgr nvarchar(256) )
AS
BEGIN
DECLARE @nold hierarchyid, @nnew hierarchyid
SELECT @nold = OrgNode FROM HumanResources.EmployeeDemo WHERE LoginID = @oldMgr ;

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT @nnew = OrgNode FROM HumanResources.EmployeeDemo WHERE LoginID = @newMgr ;

SELECT @nnew = @nnew.GetDescendant(max(OrgNode), NULL) 
FROM HumanResources.EmployeeDemo WHERE OrgNode.GetAncestor(1)=@nnew ;

UPDATE HumanResources.EmployeeDemo  
SET OrgNode = OrgNode.Reparent(@nold, @nnew)
WHERE @nold.IsDescendant(OrgNode) = 1 ;

COMMIT TRANSACTION
END ;
GO