从插入触发器更新时更新触发器后不触发
Posted
技术标签:
【中文标题】从插入触发器更新时更新触发器后不触发【英文标题】:Not firing after update trigger when updating from insert trigger 【发布时间】:2016-08-16 11:59:22 【问题描述】:我在一张表上有两个触发器,一个在插入时触发并使用来自其他表的附加信息更新该行
CREATE TRIGGER [dbo].[eTteamTg]
ON [dbo].[entryTable]
AFTER INSERT
AS
BEGIN
UPDATE entryTable
SET shiftTeam = (SELECT TOP 1 shiftTeamMemb.teamId
FROM shiftTeamMemb
WHERE shiftTeamMemb.personalNumber = i.personalNumber)
FROM entryTable
INNER JOIN inserted i ON i.ID = entryTable.ID
END
第二个在更新后触发
CREATE TRIGGER [dbo].[eThistoryUpdTg] ON [dbo].[entryTable]
AFTER update
AS
BEGIN
INSERT INTO eThistory(my columns)
SELECT
*, HOST_Name() + ' ' + SUSER_NAME() + ' Upd', GETDATE()
FROM
deleted
END
当我使用AFTER INSERT
触发器更新行时,我需要做的是不触发 AFTER UPDATE
触发器。有可能吗?
【问题讨论】:
您的insert
触发器似乎已损坏。子查询是不相关的(它引入了对inserted
的单独引用,而不是我猜你正在尝试做的,引用i
),因此多行插入将产生一个错误,类似于“子查询返回更多超过一个值”。
哦,我现在明白了,更新了问题@Damien_The_Unbeliever
对不起,我错了。它不会返回那个错误。相反,它会默默地破坏您的数据,因为您已经使用top 1
强制它这样做了。同样,该子查询是不相关的。因此,如果 inserted
包含 多个 行,其中 不同 personalNumber
值,这些值中的 一个 将成功导致在 @987654331 中发生查找@ 然后 每一 行最初插入将收到该值。
使用TOP 1
没有明确的ORDER BY
是没有意义的——你希望得到哪一行?由于没有ORDER BY
,因此无法保证任何排序 - 你基本上得到一个 任意 行 .... 这真的是你要找的吗??
我同意你的观点,这个子查询写得不好,我稍后会重写它,现在我需要解决我在这个问题中的主要问题。
【参考方案1】:
我建议你将这两个触发器合并为一个:
CREATE TRIGGER [dbo].[eTteamTg]
ON [dbo].[entryTable]
AFTER INSERT, UPDATE
AS
BEGIN
UPDATE entryTable
SET shiftTeam = (SELECT TOP 1 shiftTeamMemb.teamId
FROM shiftTeamMemb
WHERE shiftTeamMemb.personalNumber = i.personalNumber)
FROM entryTable
INNER JOIN inserted i ON i.ID = entryTable.ID
INSERT INTO eThistory(my columns)
SELECT
*, HOST_Name() + ' ' + SUSER_NAME() + ' Upd', GETDATE()
FROM
deleted
END
那么在INSERT之后,会更新shiftTeam
,不会使用`deleted1。
在 UPDATE 之后,它将更新 shiftTeam
并使用 deleted
来获取以前的(甚至是以上更新的)值。
或者如果您不需要更新 shiftTeam
以防在此表上进行 UPDATE,您可以添加 IF 语句:
CREATE TRIGGER [dbo].[eTteamTg]
ON [dbo].[entryTable]
AFTER INSERT, UPDATE
AS
BEGIN
IF (SELECT COUNT(*) FROM deleted) = 0 --That means it was INSERT
BEGIN
UPDATE entryTable
SET shiftTeam = (SELECT TOP 1 shiftTeamMemb.teamId
FROM shiftTeamMemb
WHERE shiftTeamMemb.personalNumber = i.personalNumber)
FROM entryTable
INNER JOIN inserted i ON i.ID = entryTable.ID
END
INSERT INTO eThistory(my columns)
SELECT
*, HOST_Name() + ' ' + SUSER_NAME() + ' Upd', GETDATE()
FROM
deleted
END
【讨论】:
太棒了!这正是我所需要的,我不知道您可以对更多操作执行相同的触发器。这种方式相当巧妙。我必须使用第二种方式,因为我只需要在插入时更新它【参考方案2】:像这样实现你的第二个触发器,
CREATE TRIGGER [dbo].[eThistoryUpdTg] ON [dbo].[entryTable]
AFTER UPDATE
AS
BEGIN
INSERT INTO eThistory (my columns)
SELECT *
,HOST_Name() + ' ' + SUSER_NAME() + ' Upd'
,GETDATE()
FROM deleted d
WHERE NOT EXISTS (
SELECT TOP 1 shiftTeamMemb.teamId
FROM shiftTeamMemb
INNER JOIN inserted I ON i.personalNumber = shiftTeamMemb.personalNumber
INNER JOIN entryTable E ON E.ID = I.ID
WHERE shiftTeamMemb.personalNumber = i.personalNumber
)
END
【讨论】:
以上是关于从插入触发器更新时更新触发器后不触发的主要内容,如果未能解决你的问题,请参考以下文章