我有以下触发器
CREATE TRIGGER [dbo].[LastActionTrigger] on [dbo].[PlanningAction]
AFTER INSERT AS
BEGIN
DECLARE @ActionID BIGINT
DECLARE @ActionNameID BIGINT
DECLARE @MilestonePlanningID BIGINT
DECLARE @Name VARCHAR(MAX)
DECLARE @log as varchar(max)
DECLARE @cmdtxt as varchar(255)
SELECT @ActionID = i.ActionID, @ActionNameID = i.ActionNameID, @MilestonePlanningID = i.MilestonePlanningID
FROM Inserted i
IF @ActionNameID NOT IN (10,11,12)
BEGIN
UPDATE MilestonePlanning SET LastPlanningActionID = @ActionID WHERE MilestonePlanningID = @MilestonePlanningID;
--LOG
SELECT @Name = AN.ActionName FROM ActionName AN WHERE AN.ActionNameID = @ActionNameID
SET @log = 'Milestone['+CAST(@MilestonePlanningID AS VARCHAR(MAX))+'] : Last Action Changed To ' + @Name
EXEC master..xp_cmdshell @cmdtxt, no_output
SELECT @cmdtxt = 'echo ' + @log + ' >> c:\database_logs\'+DB_NAME(DB_ID())+'_'+CAST(@MilestonePlanningID AS VARCHAR(MAX))+'.txt'
SET @log = 'UPDATE MilestonePlanning SET LastPlanningActionID = '+CAST(@ActionID AS VARCHAR(MAX))+' WHERE MilestonePlanningID = ' + CAST(ISNULL(@MilestonePlanningID,0) AS VARCHAR(MAX))
EXEC master..xp_cmdshell @cmdtxt, no_output
SELECT @cmdtxt = 'echo ' + @log + ' >> c:\database_logs\'+DB_NAME(DB_ID())+'_'+CAST(@MilestonePlanningID AS VARCHAR(MAX))+'.txt'
EXEC master..xp_cmdshell @cmdtxt, no_output
EXEC(@log)
END
END
我们的系统使用播放暂停芬兰语和其他操作,其中所有操作都与此触发器一起使用,但有时Update语句无声地失败或永远不会发生,但是日志文件被创建(出于测试目的,我写了日志文件,看看发生了什么)
编辑: 我尝试了以下,但仍然无法正常工作,MilestonePlanning行得到更新,有些不会
ALTER TRIGGER [dbo].[LastActionTrigger] on [dbo].[PlanningAction]
AFTER INSERT AS
BEGIN
UPDATE MilestonePlanning SET LastPlanningActionID = i.ActionID
FROM Inserted i
WHERE MilestonePlanning.MilestonePlanningID = i.MilestonePlanningID AND i.ActionNameID NOT IN (10,11,12)
END
编辑:上面的Trigger Worked,主要问题是在代码后面某个动作更新了MilestonePlanning触发器触发后,这导致前一个LastPlanningActionID被重置
答案 0 :(得分:2)
您的根本缺陷是,您似乎希望触发器每行一次 - 这在SQL Server中是 NOT 。相反,触发器会在每个语句时触发,并且伪表Inserted
和Deleted
可能(并且将!)包含多行强>
鉴于该表可能包含多行 - 您希望在这里选择哪一行?
SELECT @ActionID = i.ActionID, @ActionNameID = i.ActionNameID, @MilestonePlanningID = i.MilestonePlanningID
FROM Inserted i
未定义 - 您可以从Inserted
中的任意行获取值 - 而忽略所有其他行.....
您需要使用Inserted
WILL 包含多行的知识重写整个触发器!您需要使用基于集合的操作 - 不要只期望Inserted
中的一行!
另外:我强烈建议不在触发器中进行任何耗时的处理 - 绝对不要调用外部依赖项,例如xp_cmdshell
。触发器在正在运行的事务的上下文中执行,任何冗长的处理都将延长该事务的执行时间。触发器应该非常灵活并且不需要进行大量处理!