2012-09-05 49 views
1

詢問一個非常簡單的問題。我實際上想在任何用戶最近插入更新和刪除記錄時跟蹤我的數據庫。通過asp.net將參數傳遞給sql觸發器

我創建了觸發器以跟蹤任何數據庫更改。

這裏是我的SQL觸發器

USE [test] 
GO 
/****** Object: Trigger [dbo].[tr_trigtest1] Script Date: 09/05/2012 16:31:18 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[tr_trigtest1] ON [dbo].[test1] FOR INSERT, UPDATE, DELETE 
AS 

DECLARE @bit INT , 
     @field INT , 
     @maxfield INT , 
     @char INT , 
     @fieldname VARCHAR(128) , 
     @TableName VARCHAR(128) , 
     @PKCols VARCHAR(1000) , 
     @sql VARCHAR(2000), 
     @UpdateDate VARCHAR(21) , 
     @UserName VARCHAR(128) , 
     @Type CHAR(1) , 
     @PKSelect VARCHAR(1000) 


--You will need to change @TableName to match the table to be audited 
SELECT @TableName = 'trigtest' 

-- date and user 
SELECT   @UserName = @UserName , 
     @UpdateDate = CONVERT(VARCHAR(8), GETDATE(), 112) 
       + ' ' + CONVERT(VARCHAR(12), GETDATE(), 114) 

-- Action 
IF EXISTS (SELECT * FROM inserted) 
     IF EXISTS (SELECT * FROM deleted) 
       SELECT @Type = 'U' 
     ELSE 
       SELECT @Type = 'I' 
ELSE 
     SELECT @Type = 'D' 

-- get list of columns 
SELECT * INTO #ins FROM inserted 
SELECT * INTO #del FROM deleted 

-- Get primary key columns for full outer join 
SELECT @PKCols = COALESCE(@PKCols + ' and', ' on') 
       + ' i.' + c.COLUMN_NAME + ' = d.' + c.COLUMN_NAME 
     FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk , 

       INFORMATION_SCHEMA.KEY_COLUMN_USAGE c 
     WHERE pk.TABLE_NAME = @TableName 
     AND  CONSTRAINT_TYPE = 'PRIMARY KEY' 
     AND  c.TABLE_NAME = pk.TABLE_NAME 
     AND  c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME 

-- Get primary key select for insert 
SELECT @PKSelect = COALESCE(@PKSelect+'+','') 
     + '''<' + COLUMN_NAME 
     + '=''+convert(varchar(100), 
coalesce(i.' + COLUMN_NAME +',d.' + COLUMN_NAME + '))+''>''' 
     FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk , 
       INFORMATION_SCHEMA.KEY_COLUMN_USAGE c 
     WHERE pk.TABLE_NAME = @TableName 
     AND  CONSTRAINT_TYPE = 'PRIMARY KEY' 
     AND  c.TABLE_NAME = pk.TABLE_NAME 
     AND  c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME 

IF @PKCols IS NULL 
BEGIN 
     RAISERROR('no PK on table %s', 16, -1, @TableName) 
     RETURN 
END 

SELECT   @field = 0, 
     @maxfield = MAX(ORDINAL_POSITION) 
     FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TableName 
WHILE @field < @maxfield 
BEGIN 
     SELECT @field = MIN(ORDINAL_POSITION) 
       FROM INFORMATION_SCHEMA.COLUMNS 
       WHERE TABLE_NAME = @TableName 
       AND ORDINAL_POSITION > @field 
     SELECT @bit = (@field - 1)% 8 + 1 
     SELECT @bit = POWER(2,@bit - 1) 
     SELECT @char = ((@field - 1)/8) + 1 
     IF SUBSTRING(COLUMNS_UPDATED(),@char, 1) & @bit > 0 
             OR @Type IN ('I','D') 
     BEGIN 
       SELECT @fieldname = COLUMN_NAME 
         FROM INFORMATION_SCHEMA.COLUMNS 
         WHERE TABLE_NAME = @TableName 
         AND ORDINAL_POSITION = @field 
       SELECT @sql = ' 
insert Audit ( Type, 
       TableName, 
       PK, 
       FieldName, 
       OldValue, 
       NewValue, 
       UpdateDate, 
       UserName) 
select ''' + @Type + ''',''' 
     + @TableName + ''',' + @PKSelect 
     + ',''' + @fieldname + '''' 
     + ',convert(varchar(1000),d.' + @fieldname + ')' 
     + ',convert(varchar(1000),i.' + @fieldname + ')' 
     + ',''' + @UpdateDate + '''' 
     + ',''' + @UserName + '''' 
     + ' from #ins i full outer join #del d' 
     + @PKCols 
     + ' where i.' + @fieldname + ' <> d.' + @fieldname 
     + ' or (i.' + @fieldname + ' is null and d.' 
           + @fieldname 
           + ' is not null)' 
     + ' or (i.' + @fieldname + ' is not null and d.' 
           + @fieldname 
           + ' is null)' 
       EXEC (@sql) 
     END 
END 

一切順利,我會得到這些細節,當任何記錄更新,插入和刪除

enter image description here

我的編碼

public partial class WebForm1 : System.Web.UI.Page 
{ 
    private testEntities entity = new testEntities(); 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     trigtest test = trigtest.Createtrigtest(10, 12); 
     entity.AddTotrigtests(test); 
     entity.SaveChanges(); 
    } 
} 

所以現在我遇到了問題。它有可能通過後端代碼將值傳遞給@username?如何修改觸發器?對不起,我仍然非常新鮮的SQL觸發器。我不知道如何修改它

+0

通過構建動態sql,該觸發器將使寫入操作非常緩慢。爲什麼不使用DDL來動態創建靜態觸發器? – StuartLC

+0

您好中午,可以公會我一些例子?我仍然非常新的sql觸發器 – user998405

回答

1

的用戶名是由函數SUser_SName()

SELECT @UserName = SUser_SName(); 

什麼樣的價值,實際上返回取決於你的EF連接字符串返回。

+1

所以有可能通過後端代碼將值傳遞給@username?對不起,我仍然爲sql觸發器。我不知道如何修改trugger – user998405

+0

是的,你可以。 http://stackoverflow.com/questions/3883613/is-it-possible-to-pass-a-parameter-to-trigger-in-sql-server-database但你可能不應該。只要改變'SELECT @UserName = @UserName'行到上面的那個。 – podiluska

+0

好的謝謝。那麼我應該在我的後端代碼中編碼? – user998405