Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Colonna di incremento automatico univoca di SQL Server nel contesto di un'altra colonna

Bene, non esiste un supporto nativo per questo tipo di colonna, ma puoi implementarlo utilizzando un trigger:

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

Non testato ma sono abbastanza sicuro che funzionerà. Se hai una chiave primaria, puoi anche implementarla come AFTER trigger (non mi piace usare INSTEAD OF trigger, sono più difficili da capire quando è necessario modificarli 6 mesi dopo).

Giusto per spiegare cosa sta succedendo qui:

  • SERIALIZABLE è la modalità di isolamento più rigoroso; garantisce che solo una transazione di database alla volta possa eseguire queste istruzioni, di cui abbiamo bisogno per garantire l'integrità di questa "sequenza". Tieni presente che ciò promuove irreversibilmente l'intera transazione, quindi non vorrai utilizzarlo all'interno di una transazione di lunga durata.

  • Il CTE preleva il numero più alto già utilizzato per ogni ID genitore;

  • ROW_NUMBER genera una sequenza univoca per ogni ID genitore (PARTITION BY ) a partire dal numero 1; lo aggiungiamo al massimo precedente se ce n'è uno per ottenere la nuova sequenza.

Probabilmente dovrei anche menzionare che se hai solo bisogno di inserire una nuova entità figlio alla volta, è meglio incanalare quelle operazioni attraverso una procedura memorizzata invece di usare un trigger:ne otterrai sicuramente prestazioni migliori . Ecco come si fa attualmente con hierarchyid colonne in SQL '08.