Bene, non esiste un supporto nativo per questo tipo di colonna, ma puoi implementarlo utilizzando un trigger:
CREATE TRIGGER tr_MyTable_Number
ON MyTable
INSTEAD OF INSERT
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN;
WITH MaxNumbers_CTE AS
(
SELECT ParentEntityID, MAX(Number) AS Number
FROM MyTable
WHERE ParentEntityID IN (SELECT ParentEntityID FROM inserted)
)
INSERT MyTable (ParentEntityID, Number)
SELECT
i.ParentEntityID,
ROW_NUMBER() OVER
(
PARTITION BY i.ParentEntityID
ORDER BY (SELECT 1)
) + ISNULL(m.Number, 0) AS Number
FROM inserted i
LEFT JOIN MaxNumbers_CTE m
ON m.ParentEntityID = i.ParentEntityID
COMMIT
Non testato ma sono abbastanza sicuro che funzionerà. Se hai una chiave primaria, puoi anche implementarla come AFTER
trigger (non mi piace usare INSTEAD OF
trigger, sono più difficili da capire quando è necessario modificarli 6 mesi dopo).
Giusto per spiegare cosa sta succedendo qui:
-
SERIALIZABLE
è la modalità di isolamento più rigoroso; garantisce che solo una transazione di database alla volta possa eseguire queste istruzioni, di cui abbiamo bisogno per garantire l'integrità di questa "sequenza". Tieni presente che ciò promuove irreversibilmente l'intera transazione, quindi non vorrai utilizzarlo all'interno di una transazione di lunga durata. -
Il CTE preleva il numero più alto già utilizzato per ogni ID genitore;
-
ROW_NUMBER
genera una sequenza univoca per ogni ID genitore (PARTITION BY
) a partire dal numero 1; lo aggiungiamo al massimo precedente se ce n'è uno per ottenere la nuova sequenza.
Probabilmente dovrei anche menzionare che se hai solo bisogno di inserire una nuova entità figlio alla volta, è meglio incanalare quelle operazioni attraverso una procedura memorizzata invece di usare un trigger:ne otterrai sicuramente prestazioni migliori . Ecco come si fa attualmente con hierarchyid
colonne in SQL '08.