Welnu, er is geen native ondersteuning voor dit type kolom, maar je zou het kunnen implementeren met een 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
Niet getest, maar ik ben er vrij zeker van dat het zal werken. Als u een primaire sleutel heeft, kunt u deze ook implementeren als een AFTER
trigger (ik gebruik niet graag INSTEAD OF
triggers, ze zijn moeilijker te begrijpen wanneer u ze 6 maanden later moet wijzigen).
Gewoon om uit te leggen wat hier aan de hand is:
-
SERIALIZABLE
is de strengste isolatiemodus; het garandeert dat slechts één databasetransactie tegelijk deze instructies kan uitvoeren, die we nodig hebben om de integriteit van deze "reeks" te garanderen. Houd er rekening mee dat dit de hele transactie onomkeerbaar promoot, dus u wilt dit niet gebruiken binnen een langlopende transactie. -
De CTE haalt het hoogste nummer op dat al is gebruikt voor elke ouder-ID;
-
ROW_NUMBER
genereert een unieke reeks voor elke ouder-ID (PARTITION BY
) beginnend bij het cijfer 1; we voegen dit toe aan het vorige maximum als er een is om de nieuwe reeks te krijgen.
Ik moet waarschijnlijk ook vermelden dat als je maar één nieuwe onderliggende entiteit tegelijk hoeft in te voegen, je die bewerkingen beter gewoon door een opgeslagen procedure kunt leiden in plaats van een trigger te gebruiken - je zult er zeker betere prestaties uit halen . Dit is hoe het momenteel wordt gedaan met hierarchyid
kolommen in SQL '08.