Bem, não há suporte nativo para esse tipo de coluna, mas você pode implementá-lo usando um gatilho:
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
Não testei, mas tenho certeza que vai funcionar. Se você tiver uma chave primária, também poderá implementá-la como
AFTER
trigger (não gosto de usar INSTEAD OF
gatilhos, eles são mais difíceis de entender quando você precisa modificá-los 6 meses depois). Só para explicar o que está acontecendo aqui:
-
SERIALIZABLE
é o modo de isolamento mais estrito; ele garante que apenas uma transação de banco de dados por vez pode executar essas instruções, que precisamos para garantir a integridade dessa "sequência". Observe que isso promove irreversivelmente toda a transação, portanto, você não desejará usar isso dentro de uma transação de longa duração.
-
O CTE pega o número mais alto já usado para cada ID pai;
-
ROW_NUMBER
gera uma sequência única para cada ID pai (PARTITION BY
) a partir do número 1; adicionamos isso ao máximo anterior se houver um para obter a nova sequência.
Eu provavelmente também deveria mencionar que, se você precisar inserir apenas uma nova entidade filho de cada vez, é melhor canalizar essas operações por meio de um procedimento armazenado em vez de usar um gatilho - você definitivamente obterá melhor desempenho com isso . É assim que é feito atualmente com
hierarchyid
colunas no SQL '08.