我正在维护某个代码,其中有一个触发器用于增加表中的一列。该列随后由第三方应用程序 A 使用。假设表名为test,有两列num1和num2。 触发器在每次将num1插入到test中时运行。以下是触发器:
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
这在简单的基于行的插入中很好用,但有另一个第三方应用程序B(叹气),它有时会对这个表进行多次插入,类似于这样,但不完全相同:
INSERT INTO [db1].[dbo].[test]
([num1])
Select db1.dbo.test.num1 from [db1].[dbo].[test]
GO
这会导致触发器行为不稳定...
现在我无法访问应用程序 A 或 B 的源代码,只能控制数据库和触发器。有没有什么方法可以通过触发器使对 num2 的更新在多次插入的情况下是正确的?
解决方案:
以下是基于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
这里提供一种基于集合的方法: SQL Server - Rewrite trigger to avoid cursor based approach
COALESCE(MAX(num2),0)
替换检查吗?” - JustAMartin