我有表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
答案 0 :(得分:1)
您的触发器仅在更新和删除时触发,这就是编辑表时触发的原因。存储过程正在执行插入操作,触发器无法检测到该插入操作。您的触发器应该是 INSERT,UPDATE,DELETE 。
答案 1 :(得分:0)
问题的关键是我在问题中提到的:
无法从App运行触发器,但我可以直接从数据库更新中触发它。
问题是应用程序使用自己的通用用户连接到DB,该用户没有Trigger的执行权限。
为了使事情变得更复杂,在应用程序级别没有例外。
修复是添加
WITH EXECUTE AS OWNER
触发器。