面向未来的INSTEAD OF INSERT触发器

时间:2014-03-12 16:26:48

标签: sql-server triggers

我在子表上创建了一个INSTEAD OF INSERT触发器,如果​​需要,它将自动在父表中创建一条记录。我有触发器工作,但我担心这将是一个维护头痛,因为我必须明确列出子表中的每个非自动编号字段。

以下是工作SQL,它应该展示我想要实现的目标:

CREATE TABLE Accts 
(AcctNum char(3) NOT NULL CONSTRAINT PK_Accts PRIMARY KEY
,StatusCode char(1))

CREATE TABLE Docs
(DocID int NOT NULL IDENTITY (1,1) CONSTRAINT PK_Docs PRIMARY KEY
,AcctNum char(3) NOT NULL CONSTRAINT FK_Doc_AcctNum FOREIGN KEY REFERENCES Accts(AcctNum)
,SavedBy varchar(30) NOT NULL
,SavedAt datetime NOT NULL)
GO

CREATE TRIGGER Tr_I_Docs ON Docs
INSTEAD OF INSERT
AS
BEGIN
  INSERT INTO Accts (AcctNum, StatusCode)
  SELECT DISTINCT i.AcctNum, 'N' FROM inserted as i
  WHERE NOT EXISTS 
    (SELECT 1 FROM Accts AS A 
     WHERE A.AcctNum=i.AcctNum);

  INSERT INTO Docs (AcctNum,   SavedBy,   SavedAt)
  SELECT          i.AcctNum, i.SavedBy, i.SavedAt FROM inserted as i;

END
GO

INSERT INTO Docs(AcctNum,SavedAt,SavedBy)
VALUES
 ('111','2014-03-12','Jim')
,('222','2014-03-13','Joe')
,('333','2014-03-14','Tom')
,('111','2014-03-21','Dan')

SELECT * FROM Accts;
GO

DROP TABLE Docs;
DROP TABLE Accts;

Docs表中更改列时,我需要记住更新此触发器。理想情况下,我想从触发器中替换这些线......

INSERT INTO Docs (AcctNum,   SavedBy,   SavedAt)
SELECT          i.AcctNum, i.SavedBy, i.SavedAt FROM inserted as i;

......有更像这样的东西:

INSERT INTO Docs SELECT * 

显然,由于Docs表中的IDENTITY列,上述内容无法正常工作。有什么建议吗?

除了使用INSTEAD OF INSERT触发器来实现我的目标之外,我还欢迎这些想法。

1 个答案:

答案 0 :(得分:1)

this answer的启发,我取代了以下几行:

INSERT INTO Docs (AcctNum,   SavedBy,   SavedAt)
SELECT          i.AcctNum, i.SavedBy, i.SavedAt FROM inserted as i;

这些行:

SELECT * INTO #Docs FROM inserted;
ALTER TABLE #Docs DROP COLUMN DocID;
INSERT INTO Docs SELECT * FROM #Docs;
DROP TABLE #Docs;

大型插入可能在性能方面存在问题,但如果应用程序仅限于一次插入一行或几行,那么应该没问题。