sql >> Base de Datos >  >> RDS >> Sqlserver

Columna de incremento automático única de SQL Server en el contexto de otra columna

Bueno, no hay soporte nativo para este tipo de columna, pero podría implementarlo usando un disparador:

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

No probado, pero estoy bastante seguro de que funcionará. Si tiene una clave principal, también podría implementarla como AFTER activador (no me gusta usar INSTEAD OF factores desencadenantes, son más difíciles de entender cuando necesita modificarlos 6 meses después).

Solo para explicar lo que está pasando aquí:

  • SERIALIZABLE es el modo de aislamiento más estricto; garantiza que solo una transacción de base de datos a la vez puede ejecutar estas declaraciones, que necesitamos para garantizar la integridad de esta "secuencia". Tenga en cuenta que esto promueve irreversiblemente toda la transacción, por lo que no querrá usar esto dentro de una transacción de larga duración.

  • El CTE recoge el número más alto ya utilizado para cada ID de padre;

  • ROW_NUMBER genera una secuencia única para cada ID principal (PARTITION BY ) a partir del número 1; agregamos esto al máximo anterior si hay uno para obtener la nueva secuencia.

Probablemente también debería mencionar que si solo necesita insertar una nueva entidad secundaria a la vez, es mejor canalizar esas operaciones a través de un procedimiento almacenado en lugar de usar un activador; definitivamente obtendrá un mejor rendimiento. . Así es como se hace actualmente con hierarchyid columnas en SQL '08.