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
4

3 回答 3

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。)

于 2009-02-02T18:31:48.323 回答
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
于 2009-02-02T18:36:51.667 回答
1

为什么不级联触发器 - 在 T2 上使用 INSERT 触发器在 T3 上执行插入。然后,您可以避免 t1_insert_trg 中的光标,而只需使用 insert - 如下所示:

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
于 2009-02-02T18:21:51.837 回答