SQL Server - Rewrite trigger to avoid cursor based approach
If I have table Test with two columns num1 and num2 and the following trigger on it which just increments num2 on inserts of num1:
DECLARE @PROC_NEWNUM1 VARCHAR (10)
DECLARE @NEWNUM2 numeric(20)
DECLARE my_Cursor CURSOR 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
Is there a way to rewrite the above using a set based approach?
(In case anyone wants to know why I am doing this, here is the background: SQL Server A t开发者_Go百科rigger to work on multiple row inserts)
Solution without temp table using Row_Number (Sql 2005 onwards only):
SELECT @MAXNUM2 = MAX(num2) FROM TEST
if @MAXNUM2 IS NULL
BEGIN
SET @MAXNUM2=0
END
UPDATE TEST
SET num2 = @MAXNUM2 + SubQuery.R
FROM
(
SELECT num1, ROW_NUMBER() OVER (ORDER BY num1) as R FROM inserted
)
SubQuery
INNER JOIN TEST on SubQuery.num1 = TEST.num1
Just an idea:
begin tran to avoid changes to test
declare @max int
select @max = max(num2) from test
create a temporary table with num1 and an autoincrement index (ex:idx (starting from 1)
insert your INSERTED into temporary table
insert into test(num1, num2) select num1, idx+@max from tmp
end tran
If I understand correctly, a normal update would get you what you want.
UPDATE TEST
SET num2 = @NEWNUM2
FROM TEST t
INNER JOIN Inserted i ON i.num1 = t.num1
DECLARE @MAXNUM2 numeric(20)
-- First make an auto increment table starting at 1
DECLARE @tmp table
(
aNum int identity(1,1),
pInsNum varchar(10)
)
INSERT INTO @tmp (pInsNum)
SELECT num1 FROM INSERTED;
-- Now find offset
SELECT @MAXNUM2 = MAX(num2) FROM TEST
IF @MAXNUM2 is null
BEGIN
SET @MAXNUM2 = 0
END
-- Do update
UPDATE TEST
SET num2 = @MAXNUM2 + aNum
FROM TEST
INNER JOIN @tmp t ON t.pInsNum = TEST.num1
Note: I was not able to test this, there might be typos.
Also, I'm sure there is a non-temp table solution using ROWNUMBER, but I am too lazy to go look up the syntax. But you can use this as a guide to get to that answer, instead of using the temp table to make the numbers from 1 to N use ROWNUMBER and add that to the offset (@maxnum2)
精彩评论