Estoy manteniendo un código que tiene un disparador en una tabla para incrementar una columna. Esa columna luego es utilizada por una aplicación de terceros A. Digamos que la tabla se llama prueba con dos columnas num1 y num2. El disparador se ejecuta en cada inserción de num1 en prueba. A continuación se presenta el gatillo:SQL Server Un disparador para trabajar en varias inserciones de fila
USE [db1]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TEST_MYTRIG] ON [dbo].[test]
FOR INSERT AS
begin
SET NOCOUNT ON
DECLARE @PROC_NEWNUM1 VARCHAR (10)
DECLARE @NEWNUM2 numeric(20)
SELECT @PROC_NEWNUM1 = num1 FROM INSERTED
select @NEWNUM2 = MAX(num2) from TEST
if @NEWNUM2 is null
Begin
set @NEWNUM2 = 0
end
set @NEWNUM2 = @NEWNUM2 + 1
UPDATE TEST SET num2 = @NEWNUM2 WHERE num1 = @PROC_NEWNUM1
SET NOCOUNT OFF
End
Esto funciona bien en simples inserciones basado fila, pero hay otra aplicación de 3 ª parte B (suspiro) que hace a veces múltiples insertos en esta mesa algo similar pero no exactamente:
INSERT INTO [db1].[dbo].[test]
([num1])
Select db1.dbo.test.num1 from [db1].[dbo].[test]
GO
Esto hace que el gatillo para comportarse de forma errática ...
Ahora bien, no tengo acceso a la fuente de la aplicación a o B y solo controla la base de datos y el disparador. ¿Hay algo que se pueda hacer con el desencadenador para que las actualizaciones hechas a num2 sean correctas en el caso de varias inserciones?
Solución:
A continuación se presenta la solución basada en el código de affan:
DECLARE @PROC_NEWNUM1 VARCHAR (10)
DECLARE @NEWNUM2 numeric(20)
DECLARE my_Cursor CURSOR FAST_FORWARD FOR SELECT num1 FROM INSERTED;
OPEN my_Cursor
FETCH NEXT FROM my_Cursor into @PROC_NEWNUM1
WHILE @@FETCH_STATUS = 0
BEGIN
select @NEWNUM2 = MAX(num2) from TEST
if @NEWNUM2 is null
Begin
set @NEWNUM2 = 0
End
set @NEWNUM2 = @NEWNUM2 + 1
UPDATE TEST SET num2 = @NEWNUM2 WHERE num1 = @PROC_NEWNUM1
FETCH NEXT FROM my_Cursor into @PROC_NEWNUM1
END
CLOSE my_Cursor
DEALLOCATE my_Cursor
Marque aquí para un enfoque basado en el conjunto: SQL Server - Rewrite trigger to avoid cursor based approach
A ** ** cursor dentro de un disparador ** ** ** es una mala idea terriblemente **; los cursores son notoriamente lentos y los cerdos de memoria, y cualquier cosa en un gatillo debe ser lo más delgado y rápido posible. Recomendaría ** fuertemente usar un enfoque diferente (de mi propia experiencia personal y agonizante con dichos constructos) –
No podría 'si @ NEWNUM2 es una verificación nula' se reemplazará con' COALESCE (MAX (num2), 0) ' – JustAMartin