【问题标题】:Creating Tricky Update Triggers创建棘手的更新触发器
【发布时间】:2017-03-19 00:41:16
【问题描述】:

救命!!我已经束手无策了!!

我一直在尝试创建一个更新触发器,以便在更新时将值插入另一个表。

TBL_PUPILS:

Age               smallint
Height            smallint
Weight            smallint
Class             int
SurName           varchar(28)
Sick_Days         smallint

困难在于每个学生都通过前 5 列的连接来唯一标识。

我已经成功创建了 INSERT TRIGGER;

CREATE Trigger [dbo].[tr_tbl_Pupils_For_Insert]
ON [dbo].[tbl_Pupils]
FOR INSERT
AS

BEGIN

DECLARE @Age smallint, @Height smallint, @Weight int, @Class int, @SurName varchar(28), @Sick_Days int

Select @Age = Age, @Height = Height, @Weight = Weight, @Class = Class, @SurName = SurName, @Sick_Days = Sick_Days
From inserted

insert into tbl_Pupil_Detail Values(@Age, @Height, @Weight, @Class, 'New', @SurName, @Sick_Days, GETDATE(), CURRENT_TIMESTAMP)

END

上面的插入触发器将用于捕获新学生加入时的日期时间等。

当修改现有学生的病假天数时,如何创建类似的 UPDATE TRIGGER?

如果您需要更多信息,请告诉我!

【问题讨论】:

  • 您的插入触发器存在缺陷,因为它无法处理多行插入。插入语句应该是“插入...选择...从插入”。您应该在 5 列上有一个复合主键,并在更新触发器中,在这 5 列上连接插入和瞳孔详细信息,以识别需要更新的行。
  • 如果学生体重增加了怎么办?还是增长?
  • 还是从一个班转到另一个班?
  • 我刚刚使用了一个具有完全相同表结构的示例表。 Sick_days 是唯一可以更新的列
  • 旁白:如果您确实需要编写一个只能处理一行的触发器,那么它应该检查inserted(或deleted)中的行数并使用@987654325 @ 或 RaIsError 自豪地宣布它的局限性。

标签: sql sql-server tsql triggers dml


【解决方案1】:

@DanGuzman、@GordonLinoff 和@ZoharPeled 在 cmets 中提出了非常有效的观点。如果给出的示例确实是您的表结构并且您仍在设计系统,那么您需要仔细考虑重新组织它,否则它会损坏,而且可能迟早发生。主要问题:永远不应该通过可能更改的字段跨表来识别学生

事实上,为你回答这个问题让我感到畏缩,但数据库重新设计完全是另一个问题,所以这里是:

CREATE Trigger [dbo].[tr_tbl_Pupils_For_Update]
ON [dbo].[tbl_Pupils]
FOR UPDATE
AS   
BEGIN

update d
set d.Sick_Days = i.Sick_Days
from tbl_Pupil_Detail d
inner join inserted i 
  on d.Age = i.Age          -- bad: don't join on fields that could change!
  and d.Height = i.Height   -- bad
  and d.Weight = i.Weight   -- bad
  and d.Class = i.Class     -- bad
  and d.SurName = i.SurName -- bad

END

inserted 表包含tbl_Pupils 表中的所有更新行:请注意我是如何通过将inserted 表与目标表(tbl_Pupil_Detail) 连接来完成更新语句的?如果在一个更新语句中更新了 tbl_Pupils 中的多行,这将一次更新多个目标行。

这对于 INSERT 和 UPDATE 触发器都很重要,因为您永远不知道何时有人会尝试批量插入或更新记录 - 如上所述将一行加载到变量中将会失败。

【讨论】:

  • 请注意,这还假设 5 个链接列在 tbl_Pupil_Detail 中命名相同。你没有在你的问题中说。
  • 谢谢各位,我知道表结构不理想,但它是继承的,无法更改。字段不会更改,我提供的列名仅代表实际列名字
  • 我明白了。不过需要指出的是,如果您是从头开始设计的!希望我的回答对您有所帮助。
猜你喜欢
  • 2019-05-03
  • 1970-01-01
  • 2017-03-27
  • 2015-12-13
  • 2012-07-31
  • 2016-05-26
  • 2016-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多