Eh bien, il n'y a pas de support natif pour ce type de colonne, mais vous pouvez l'implémenter à l'aide d'un déclencheur :
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
Pas testé mais je suis sûr que ça marchera. Si vous avez une clé primaire, vous pouvez également l'implémenter en tant que AFTER
déclencheur (je n'aime pas utiliser INSTEAD OF
déclencheurs, ils sont plus difficiles à comprendre lorsque vous devez les modifier 6 mois plus tard).
Juste pour expliquer ce qui se passe ici :
-
SERIALIZABLE
est le mode d'isolement le plus strict ; il garantit qu'une seule transaction de base de données à la fois peut exécuter ces instructions, dont nous avons besoin pour garantir l'intégrité de cette "séquence". Notez que cela favorise de manière irréversible l'intégralité de la transaction, vous ne voudrez donc pas l'utiliser dans le cadre d'une transaction de longue durée. -
Le CTE récupère le numéro le plus élevé déjà utilisé pour chaque identifiant parent ;
-
ROW_NUMBER
génère une séquence unique pour chaque identifiant parent (PARTITION BY
) à partir du chiffre 1 ; nous ajoutons ceci au maximum précédent s'il y en a un pour obtenir la nouvelle séquence.
Je devrais probablement également mentionner que si vous n'avez besoin d'insérer qu'une seule nouvelle entité enfant à la fois, vous feriez mieux de simplement canaliser ces opérations via une procédure stockée au lieu d'utiliser un déclencheur - vous obtiendrez certainement de meilleures performances. . Voici comment cela se passe actuellement avec hierarchyid
colonnes dans SQL '08.