Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Colonne d'auto-incrémentation unique SQL Server dans le contexte d'une autre colonne

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.