Cóż, nie ma natywnej obsługi tego typu kolumn, ale możesz ją zaimplementować za pomocą wyzwalacza:
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
Nie testowano, ale jestem pewien, że zadziała. Jeśli masz klucz podstawowy, możesz również zaimplementować go jako AFTER
wyzwalacz (nie lubię używać INSTEAD OF
wyzwalacze, trudniej je zrozumieć, gdy trzeba je zmodyfikować 6 miesięcy później).
Wystarczy wyjaśnić, co się tutaj dzieje:
-
SERIALIZABLE
jest najściślejszym trybem izolacji; gwarantuje, że tylko jedna transakcja bazy danych na raz może wykonać te instrukcje, których potrzebujemy, aby zagwarantować integralność tej „sekwencji”. Pamiętaj, że nieodwracalnie promuje to całą transakcję, więc nie będziesz chciał używać tego w długotrwałej transakcji. -
CTE wybiera najwyższy numer już użyty dla każdego identyfikatora rodzica;
-
ROW_NUMBER
generuje unikalną sekwencję dla każdego identyfikatora rodzica (PARTITION BY
) zaczynając od cyfry 1; dodajemy to do poprzedniego maksimum, jeśli jest jeden, aby uzyskać nową sekwencję.
Powinienem również wspomnieć, że jeśli potrzebujesz wstawić tylko jedną nową jednostkę podrzędną na raz, lepiej po prostu przenieść te operacje za pomocą procedury składowanej zamiast używać wyzwalacza — na pewno uzyskasz dzięki temu lepszą wydajność . Tak to się obecnie robi z hierarchyid
kolumny w SQL '08.