2009-02-02 94 views
2

MS SQL Server沒有行級觸發器,是否正確?如果我需要從觸發器中插入一行,然後插入另一行,根據第一次插入的結果,光標會是最好的解決方案嗎?替代行級觸發器?

例如,是否有更好的方法來做到這一點:

CREATE TABLE t1 (foo int) 
CREATE TABLE t2 (id int IDENTITY, foo int) 
CREATE TABLE t3 (t2_id int) 

GO 

CREATE TRIGGER t1_insert_trg ON t1 FOR INSERT AS 
    DECLARE c CURSOR FOR 
     SELECT foo FROM inserted 
    DECLARE @foo int 
    OPEN c 
    FETCH NEXT FROM c INTO @foo 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     INSERT INTO t2 (foo) VALUES (@foo) 
     INSERT INTO t3 (t2_id) VALUES (@@IDENTITY) 
     FETCH NEXT FROM c INTO @foo 
    END 
    CLOSE c 
    DEALLOCATE c 

回答

3

我假設你在2005年或更好?如果是這樣,查看OUTPUT子句,你不應該需要行級觸發器。例如:

USE tempdb; 
GO 

CREATE TABLE t1 (foo int); 
CREATE TABLE t2 (id int IDENTITY, foo int); 
CREATE TABLE t3 (t2_id int); 
GO 

CREATE TRIGGER t1_insert ON t1 
FOR INSERT AS 
BEGIN 
    DECLARE @new_rows TABLE(new_id INT, old_foo INT); 

    INSERT t2(foo) 
     OUTPUT inserted.id, inserted.foo 
     INTO @new_rows 
    SELECT foo 
    FROM inserted; 

    INSERT t3 SELECT new_id FROM @new_rows; 
END 
GO 

INSERT t1(foo) SELECT 1 UNION ALL SELECT 5; 
SELECT * FROM t1; 
SELECT * FROM t2; 
SELECT * FROM t3; 
GO 

DROP TABLE t1,t2,t3; 

你也可以通過在T1上插入一個觸發器來插入T2,然後在T2插入T3的觸發器來管理這個事件。這不會是有效的恕我直言,也不容易管理,但我會提交,它更容易遵循(如果你堅持2000年,可能是唯一的選擇)。兩者都可以是基於集合的,並且不需要遊標或任何其他逐行處理方法。

USE tempdb; 
GO 

CREATE TABLE t1 (foo int); 
CREATE TABLE t2 (id int IDENTITY, foo int); 
CREATE TABLE t3 (t2_id int); 
GO 

CREATE TRIGGER t1_insert ON t1 
FOR INSERT AS 
BEGIN  
    INSERT t2(foo) 
    SELECT foo FROM inserted; 
END 
GO 

CREATE TRIGGER t2_insert ON t2 
FOR INSERT AS 
BEGIN 
    INSERT t3(t2_id) 
    SELECT id FROM inserted; 
END 
GO 

INSERT t1(foo) SELECT 1 UNION ALL SELECT 5; 
SELECT * FROM t1; 
SELECT * FROM t2; 
SELECT * FROM t3; 
GO 

DROP TABLE t1,t2,t3; 

(順便說一句,如果你要的標識值,使用SCOPE_IDENTITY(),而不是@@ IDENTITY)

+0

謝謝,我真的很喜歡你的解決方案與OUTPUT! – Alvis 2009-02-02 19:40:11

1

爲什麼不級聯觸發器 - 在T2使用INSERT觸發器來T3執行插入。那麼你可以避免t1_insert_trg中的光標,並使用插入 - 如在:

CREATE TRIGGER t1_insert_trg ON t1 FOR INSERT AS 
    INSERT INTO t2 
    SELECT foo FROM inserted -- fires t2 INSERTED trigger 

CREATE TRIGGER t2_insert_trg ON t2 FOR INSERT AS 
    INSERT INTO t3 
    SELECT id FROM inserted 
2

你也許能夠避免光標或需要知道插入什麼身份使用以下插入。

Insert INTO t2 (foo) Select foo from inserted 
Insert into t3 (t2_id) Select t2.id from t2 
inner join inserted i on t2.foo = i.foo