数据库触发器:插入时
Posted
技术标签:
【中文标题】数据库触发器:插入时【英文标题】:Database Triggers: On Insert 【发布时间】:2011-11-23 12:14:57 【问题描述】:这是一个简单的例子。
我想在Table1 (Name, Age, Sex)
中插入数据。该表在插入数据时会自动增加serial#
(int)。
我想在Table1 insert
上放置一个触发器,以便在插入数据后,它会从Table1
中提取serial#
(int) 并将Serial#
和Name
放入Table2
和@987654329 @ 和 some other data
中的 Table3
。
可以通过触发器实现吗?
或者,我应该从table1
中选择(最后一个)Serial 并通过手动增加它来调用其他表上的插入,在我曾经插入Table1
的同一SP
中?
哪种方法更好?
编辑 1: 假设表:
Serial | UID | Name | Age | Sex | DateTimeStamp
(int | uniqueidentifier | nvarchar | smallint | nchar | DateTime )
默认NewID()
和默认GetDate()
作为UID
和DateTimeStamp
,INSERTED
表会在 DatetimeStamp 字段中具有 Datetime-Of-Insertion 吗?意思是,我最初没有输入任何 Serial、GUID 或 DatetimeStamp,它们会出现在 INSERTED 表中吗?
编辑2:
你能给我指点关于触发器的好书/文章吗?我读了mastering SQL server 2005,并没有从中得到太多。谢谢!
【问题讨论】:
YES - 您的INSERTED
表将具有这些值!
【参考方案1】:
当然,您可以使用触发器来执行此操作 - 类似于:
CREATE TRIGGER trg_Table1_INSERT
ON dbo.Table1 AFTER INSERT
AS BEGIN
INSERT INTO dbo.Table2(SerialNo, Name)
SELECT SerialNo, Name
FROM Inserted
INSERT INTO dbo.Table3(SomeOtherCol)
SELECT SomeOtherCol
FROM Inserted
END
或者你需要在这里做的任何事情......
重要的是要了解触发器将被调用每个语句一次 - 而不是每插入行一次。因此,如果您有一个插入 10 行的语句,您的触发器将被调用一次,伪表 Inserted
将包含已插入语句中的这 10 行。
【讨论】:
所以,T1 将有 10 行,INSERTED 将有 10 行,但 T2 和 T3 不会?你说的是这个吗? @AnubhavSaini:是的,是的,不是的。是的,Table1
将有 10 行,因此,Inserted
将有 10 行。您需要考虑到这一点,例如您需要知道并相应地进行编程(许多开发人员总是假设Inserted
中只有一行)。不 - 使用我上面的代码,Table2
和 Table3
将也获得 10 个新行!
@marc_s 只是为了清楚起见,每个语句调用一次触发器,而不是每个批处理一次(除非可能是这种情况,批处理只是一个语句)
@RalphShillington:抱歉 - 是的,你是对的 - 每个语句一次。最重要的是:不是每行一次!对于许多总是认为Inserted
只是单行并执行SELECT FROM Inserted.....
并因多行而失败的人来说,这就是“杀手”
@marc_s,每次在Table1中插入都会将所有行从Inserted into Table2插入(INSERT INTO dbo.Table2(SerialNo, Name) SELECT SerialNo, Name FROM Inserted),这个不能接受!
【参考方案2】:
是的,这可以通过触发器实现。
当您使用INSERT
触发器时,您可以访问表示要插入的行的INSERTED
逻辑表,其中包含新ID 的值。
【讨论】:
【参考方案3】:是的,可以通过触发器来实现,但请记住,TRIGGER 不接受任何输入,也不提供任何输出,因此您只能通过在触发器中查询来收集所需的数据,但要满足插入到你的 Table2 和 Table3
CREATE TRIGGER tr_YourDesiredTriggerName ON Table1
FOR INSERT
AS
BEGIN
-- Inserting data to Table2
INSERT INTO Table2( Serial, Name)
SELECT i.Serial, i.Name
FROM Table1 AS t1 INNER JOIN Inserted AS i ON t1.Serial = i.Serial
AND i.Serial NOT IN ( SELECT t2.Serial FROM Table2 AS t2 )
-- Inserting data to Table3
INSERT INTO Table3( Serial, OtherData) -- select from other table
SELECT i.Serial, OtherData
FROM OtherTable AS ot INNER JOIN Inserted AS i ON ot.Serial = i.Serial
AND i.Serial NOT IN ( SELECT t3.Serial FROM Table3 AS t3 )
END
【讨论】:
【参考方案4】:如果您无法控制插入源,请使用触发器。如果您确实可以控制插入源,则可以修改插入过程以添加辅助表行。
您还可以控制未来的插入吗?如果为这个表创建了另一个插入怎么办?如果您使用触发器,那么辅助插入也将自动处理。如果不是,那么第二次插入过程可能会省略第二次插入。根据您的应用程序,这可能是好是坏。
【讨论】:
以上是关于数据库触发器:插入时的主要内容,如果未能解决你的问题,请参考以下文章
是否可以创建一个触发器,该触发器在将记录插入一个数据库但最终插入另一个数据库时执行?