Е, няма собствена поддръжка за този тип колона, но можете да я внедрите с помощта на тригер:
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
Не е тестван, но съм почти сигурен, че ще работи. Ако имате първичен ключ, можете също да приложите това като AFTER
тригер (не обичам да използвам INSTEAD OF
задействания, те са по-трудни за разбиране, когато трябва да ги промените 6 месеца по-късно).
Само за да обясня какво се случва тук:
-
SERIALIZABLE
е най-строгият режим на изолация; той гарантира, че само една транзакция на база данни в даден момент може да изпълни тези изрази, които са ни необходими, за да гарантираме целостта на тази "последователност". Имайте предвид, че това необратимо насърчава цялата транзакция, така че няма да искате да използвате това вътре в дълготрайна транзакция. -
CTE взема най-голямото вече използвано число за всеки родителски ID;
-
ROW_NUMBER
генерира уникална последователност за всеки родителски идентификатор (PARTITION BY
) като се започне от числото 1; добавяме това към предишния максимум, ако има такъв, за да получим новата последователност.
Вероятно трябва също така да спомена, че ако трябва да вмъквате само един нов дъщерен обект наведнъж, по-добре е просто да насочите тези операции през съхранена процедура, вместо да използвате тригер - определено ще получите по-добра производителност от това . Ето как се прави в момента с hierarchyid
колони в SQL '08.