[英]Audit table update trigger does not work using a stored procedure
I have table tblA
我有表tblA
Which has a trigger defined on it, if any rows are updated it writes the changes to an audit table.上面定义了一个触发器,如果有任何行被更新,它会将更改写入审计表。
Now if on SQL Server I right click and edit a row directly, I see changes go to the audit table.现在,如果在 SQL Server 上我右键单击并直接编辑一行,我会看到更改转到审计表。
If I call a stored procedure to do an update, I do see tblA
updated but the changed values do not go into the audit table.如果我调用存储过程进行更新,我会看到tblA
已更新,但更改后的值不会进入审计表。 It seems like the trigger does not get fired at all.似乎触发器根本没有被触发。
What difference is there between directly editing a table or updating through a stored procedurein term of the trigger being fired.就触发的触发器而言,直接编辑表或通过存储过程更新之间有什么区别。
Trigger
USE [dbSuppHousing]
GO
/****** Object: Trigger [dbo].[tblSurvey_trigger] Script Date: 9/22/2015 2:32:51 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/* =============================================
Create date: 08/27/15
Description: Trigger to Add audit records to audtSurvey
// =============================================*/
ALTER TRIGGER [dbo].[tblSurvey_trigger] on [dbo].[tblSurvey]
FOR UPDATE,DELETE
AS
SET NOCOUNT ON
Declare @FieldName varchar(100)
, @Deleted varchar(4000)
, @Inserted varchar(4000)
, @SurveyID numeric
, @LoginName varchar(100)
Declare @currentDate datetime = null
SET @currentDate = getdate()
Set @Deleted = ''
Set @Inserted = ''
Select * into #Deleted From Deleted
Select * into #Inserted From Inserted
Create Table #DT ([NameValue] varchar(1000))
Create Table #IT ([NameValue] varchar(1000))
Begin Transaction
Declare auSurveyCur cursor for Select Survey_ID from #Deleted Order By Survey_ID
open auSurveyCur
fetch next from auSurveyCur into @SurveyID
while @@fetch_status = 0
Begin
Declare auU cursor
for Select [name] from syscolumns where id = object_id('dbo.tblSurvey')
open auU
fetch next from auU into @FieldName
while @@fetch_status = 0
Begin
Insert into #DT execute ('Select ' + @FieldName + ' From #Deleted Where Survey_ID = ' + @SurveyID)
Insert into #IT execute ('Select ' + @FieldName + ' From #Inserted Where Survey_ID = ' + @SurveyID)
Set @Deleted = (Select isnull(NameValue,'--') From #DT)
Set @Inserted = (Select isnull(NameValue,'--') From #IT)
If (@Deleted <> @Inserted)
Begin
SELECT @LoginName=Login_Name
From Inserted Where Survey_ID=@SurveyID
if @Deleted = '--' begin set @Deleted = null end
if @Inserted = '--' begin set @Inserted = null end
--@ForWhat=1 means info is for tbSurvey
--In future there may be more tables for auditing and we use same
--Stored procedure to insert audit. Each table has its own audit table.
Execute dbo.InsertauInfo @Surv_ID=@SurveyID
, @auSurveyFieldName=@FieldName
, @auSurveyChangedFrom=@Deleted
, @auSurveyChangedTo=@Inserted
, @auSurveyUpdatedBy=@LoginName
, @auSurveyUpdateDate=@currentDate
, @ForWhat=1
End
Delete From #DT
Delete From #IT
fetch next from auU into @FieldName
End
close auU
deallocate auU
fetch next from auSurveyCur into @SurveyID
END
close auSurveyCur
deallocate auSurveyCur
Commit Transaction
Code for InsertauInfo
InsertauInfo
代码
ALTER PROCEDURE [dbo].[InsertauInfo]
@Surv_ID bigint,
@auSurveyFieldName varchar(100),
@auSurveyChangedFrom varchar(max),
@auSurveyChangedTo varchar(max),
@auSurveyUpdatedBy varchar(100),
@auSurveyUpdateDate datetime,
@ForWhat int
AS
BEGIN
SET NOCOUNT ON;
IF (@ForWhat=1)
BEGIN
INSERT INTO auSurvey
( Survey_ID
, auSurveyFieldName
, auSurveyChangedFrom
, auSurveyChangedTo
, auSurveyUpdateDate
, auSurveyUpdatedBy
)
VALUES
( @Surv_ID
, @auSurveyFieldName
, @auSurveyChangedFrom
, @auSurveyChangedTo
, @auSurveyUpdateDate
, @auSurveyUpdatedBy
)
END
--ELSE IF (@ForWhat=2)
-- BEGIN
-- INSERT INTO ABC
-- END
END
Example OF stored procedure which does not cause trigger to fire:不会导致触发器触发的存储过程示例:
OK I'm going crazy but if I Run this very simpple stored procedure directly in DB tirgger gets fired.好吧,我快疯了,但是如果我直接在 DB tiorger 中运行这个非常简单的存储过程,则会被解雇。 But if I run from my C# web, Stored procedure will run since tblSurvey gets updated but trigger wont get fired.但是如果我从我的 C# web 运行,存储过程将运行,因为 tblSurvey 得到更新但触发器不会被触发。
ALTER PROCEDURE [dbo].[spUpdateSurveyDataTest]
AS
BEGIN
Update tblSurvey
Set
[s1FirstName]='YES TRIGGER WORKS for sureYES'
Where Survey_Id=327
END
Your trigger only fires on updates and deletes which is why it fired when you edited the table.您的触发器仅在更新和删除时触发,这就是它在您编辑表时触发的原因。 The stored procedure is performing an insert which is undetected by your trigger.存储过程正在执行触发器未检测到的插入。 Your trigger should be for INSERT,UPDATE,DELETE .您的触发器应该用于INSERT,UPDATE,DELETE 。
The point of matter was as I mentioned in the question:问题的关键是我在问题中提到的:
Trigger could not be run from App but I was able to fire it directly from a database update.触发器无法从 App 运行,但我能够直接从数据库更新中触发它。
The problem was application was connecting to DB with its own generic User which did not have Execute permission for Trigger.问题是应用程序使用自己的通用用户连接到数据库,该用户没有触发器的执行权限。
To make things more complicated there was no exception at application level.为了使事情变得更复杂,应用程序级别也不例外。
The fix was to add解决方法是添加
WITH EXECUTE AS OWNER
To the trigger.到触发器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.