Tja, det finns inget inbyggt stöd för den här typen av kolumner, men du kan implementera det med en utlösare:
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
Inte testat men jag är ganska säker på att det kommer att fungera. Om du har en primärnyckel kan du även implementera denna som en AFTER
trigger (jag ogillar att använda INSTEAD OF
utlösare är de svårare att förstå när du behöver ändra dem 6 månader senare).
Bara för att förklara vad som händer här:
-
SERIALIZABLE
är det strängaste isoleringsläget; det garanterar att endast en databastransaktion åt gången kan exekvera dessa uttalanden, vilket vi behöver för att garantera integriteten för denna "sekvens". Observera att detta oåterkalleligt främjar hela transaktionen, så du vill inte använda detta i en långvarig transaktion. -
CTE:n hämtar det högsta numret som redan används för varje förälder-ID;
-
ROW_NUMBER
genererar en unik sekvens för varje förälder-ID (PARTITION BY
) från siffran 1; vi lägger till detta till det tidigare maximum om det finns en för att få den nya sekvensen.
Jag borde nog också nämna att om du bara behöver infoga en ny underordnad enhet åt gången, är det bättre att du bara kanalisera dessa operationer genom en lagrad procedur istället för att använda en trigger - du kommer definitivt att få bättre prestanda av det . Så här görs det för närvarande med hierarchyid
kolumner i SQL '08.