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

时间:2015-09-22 18:28:15

标签: sql sql-server

我有表tblA

在其上定义了触发器,如果​​更新了任何行,则会将更改写入审计表。

现在,如果在SQL Server上我右键单击并直接编辑一行,我会看到更改转到审计表。

如果我调用存储过程进行更新,我确实看到tblA已更新,但更改后的值不会进入审计表。似乎触发器根本没有被触发。

直接编辑表格或通过存储过程在被触发的触发器的术语之间有什么区别。

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

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

不会导致触发的存储过程示例:

好的我疯了但如果我直接在DB tirgger中运行这个非常简单的存储过程就会被解雇。但是如果我从我的C#web运行,存储过程将会运行,因为tblSurvey会更新,但触发器不会被触发。

ALTER PROCEDURE [dbo].[spUpdateSurveyDataTest]


AS
BEGIN

Update tblSurvey

Set 
[s1FirstName]='YES TRIGGER WORKS  for sureYES'
Where Survey_Id=327


END

2 个答案:

答案 0 :(得分:1)

您的触发器仅在更新和删除时触发,这就是编辑表时触发的原因。存储过程正在执行插入操作,触发器无法检测到该插入操作。您的触发器应该是 INSERT,UPDATE,DELETE

答案 1 :(得分:0)

问题的关键是我在问题中提到的:

无法从App运行触发器,但我可以直接从数据库更新中触发它。

问题是应用程序使用自己的通用用户连接到DB,该用户没有Trigger的执行权限。

为了使事情变得更复杂,在应用程序级别没有例外。

修复是添加

WITH EXECUTE AS OWNER 

触发器。