2010-02-02 34 views
3

如果我有表測試有兩列NUM1NUM2和它下面的觸發器,它只是增加對NUM1的刀片NUM2:SQL服務器 - 重寫觸發器,以避免基於遊標的方法

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 

有沒有辦法使用基於集合的方法重寫上述內容?

(如果有人想知道爲什麼我這樣做,這裏的背景是: SQL Server A trigger to work on multiple row inserts

解決方案,而無需使用ROW_NUMBER臨時表(SQL 2005年起只):

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 
+1

觸發器是魔鬼玩具。 。:D – 2010-02-02 11:53:54

回答

0
DECLARE @MAXNUM2 numeric(20) 

-- First make an auto increment table starting at 1 
DEFINE @tmp 
( 
    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 ON @tmp.pInsNum = TEST.num1 

注:我不能對此進行測試,可能會有錯別字。

另外,我確定有一個使用ROWNUMBER的非臨時表解決方案,但我懶得去查找語法。但是你可以用這個作爲指導來得到答案,而不是使用臨時表來使數字從1到N使用ROWNUMBER並將其添加到偏移量(@ maxnum2)

+0

這工作正常,但「DEFINE @tmp」應該是「DECLARE @tmp表」和內部聯接應該使用別名:「INNER JOIN @tmp T ON T .pInsNum = TEST.num1「。 – pug 2010-02-03 06:40:56

+0

@pug:FYI你也可以做[@tmp],儘管我同意別名更好。 – ErikE 2010-02-07 07:53:23

1

只是一個想法:

的begin tran,以避免改變測試

聲明@Max在噸

選擇@Max = MAX(NUM2)從測試

創建NUM1臨時表和自動增量索引(例如:IDX(從1開始)

插入您插入到臨時表

插入到測試(NUM1,NUM2)選擇NUM1,從TMP IDX + @最大

端TRAN

+0

有趣,我寫我的時候沒有看到你的答案。那麼我編碼這個算法(反式除外)在我的答案。有一個問題,如果你在觸發器中有交易,@munissor是否有任何死鎖的機會? – Hogan 2010-02-02 13:57:57

+0

是的,有死鎖的可能性,觸發器就像任何其他查詢 – munissor 2010-02-02 15:26:40

1

如果我正確理解,一個正常更新會讓你得到你想要的。

UPDATE TEST 
SET  num2 = @NEWNUM2 
FROM TEST t 
     INNER JOIN Inserted i ON i.num1 = t.num1