简体   繁体   English

审计表更新触发器使用存储过程不起作用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM