Hierarchyid è un nuovo tipo dato introdotto con SQL Server 2008 finalizzato alla gestione di strutture gerarchiche.
Tradizionalmente la soluzione al problema della gerarchizzazione dei dati si risolve attraverso l'uso di una doppia chiave di cui viene dotata ogni entità: la chiave principale rappresenta l'entità stessa mentre la chiave secondaria rappresenta il padre diretto.
La nuova soluzione di SQL Server, come vedremo, utilizza un'unica chiave che indica sia la relazione dell'entità con il padre, che la sua posizione nell'albero.
Preparazione dell'ambiente
Per effettuare qualche esperimento creiamo una tabella come quella indicata dallo script seguente.
CREATE TABLE Tree(
TreeId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
TreePosition hierarchyid NOT NULL UNIQUE,
Name varchar(50) NOT NULL,
Surname varchar(50) NOT NULL,
MilitaryRank varchar(50) NULL
)
La gerarchia che andiamo a rappresentare è di tipo militare.
I campi che descrivono le singole entità (soldati) sono: nome (Name), cognome (Surname) e grado (MilitaryRank).
La tabella è dotata anche di un campo hierarchyid (TreePosition) che serve a costruire la gerarchia vera e propria e da un'identità che funge da chiave primaria (TreeId).
Il campo hierarchyid è decorato dell'attributo UNIQUE per delegare a SQL Server il controllo di univocità dei nodi.
Nativamente HierarchyId non ha preclusioni nel creare nodi la cui posizione sia perfettamente sovrapponibile cioè non teme le duplicazioni di nodi.
Se permettessimo la sovrapponibilità dei nodi, togliendo il vincolo UNIQUE dal campo TreePosition, riusciremmo comunque ad ottenere una struttura gerarchica organizzata a livelli ma non sarebbe più possibile imporre un ordinamento orizzontale tra gli elementi e, cosa anche più importante, non riusciremmo più ad attribuire i figli di un nodo duplicato al giusto padre.
Il consiglio è senza dubbio di mantenere l'univocità delle posizioni.
Un'altra possibilità da valutare nella progettazione della tabella è quella di promuovere il campo hierarchyid a chiave primaria clustered. Il vantaggio in questo caso risiede nel fatto che si riuscirebbe ad ottenere una maggiore velocità di selezione, riordinamento o spostamento dei nodi dell'albero.
Il campo TreeId diventa utile quando è necessario riferirsi ai record (nelle clausole WHERE) senza dover per forza utilizzare il contenuto del campo TreePosition, che è un po' ostico da trattare rispetto ad un campo Int.