Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Coluna de incremento automático exclusiva do SQL Server no contexto de outra coluna


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.