Nå, der er ingen indbygget understøttelse af denne type kolonne, men du kan implementere den ved hjælp af en 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
Ikke testet, men jeg er ret sikker på det vil virke. Hvis du har en primær nøgle, kan du også implementere denne som en AFTER
trigger (jeg kan ikke lide at bruge INSTEAD OF
triggere, er de sværere at forstå, når du skal ændre dem 6 måneder senere).
Bare for at forklare, hvad der foregår her:
-
SERIALIZABLE
er den strengeste isolationstilstand; det garanterer, at kun én databasetransaktion ad gangen kan udføre disse udsagn, som vi har brug for for at garantere integriteten af denne "sekvens". Bemærk, at dette irreversibelt fremmer hele transaktionen, så du vil ikke bruge dette i en langvarig transaktion. -
CTE'en henter det højeste tal, der allerede er brugt for hvert forældre-id;
-
ROW_NUMBER
genererer en unik sekvens for hvert overordnet ID (PARTITION BY
) startende fra tallet 1; vi tilføjer dette til det tidligere maksimum, hvis der er en til at få den nye sekvens.
Jeg skal nok også nævne, at hvis du kun har brug for at indsætte en ny underordnet enhed ad gangen, er du bedre stillet bare at kanalisere disse operationer gennem en lagret procedure i stedet for at bruge en trigger - du vil helt sikkert få bedre ydeevne ud af det . Sådan gøres det i øjeblikket med hierarchyid
kolonner i SQL '08.