-
-
/*
Dynamic Audit Trigger Table and Code
Paul Nielsen www.IsNotNull.com
This sample script adds the dynamic audit trigger to
northwind Customers and Products table. -
Version 1.1 - Aug 6,2001
-
*/
-
USE northwind
-
-------------------------------------------------------------
-- Create the table to store the Audit Trail -
IF Exists (SELECT * FROM sysobjects WHERE NAME = 'Audit')
DROP TABLE Audit -
Go
CREATE TABLE Audit (
AuditID UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL
CONSTRAINT DF_Audit_AuditID DEFAULT (NEWID())
CONSTRAINT PK_Audit PRIMARY KEY NONCLUSTERED (AuditID),
AuditDate DATETIME NOT NULL,
SysUser VARCHAR(50) NOT NULL,
Application VARCHAR(50) NOT NULL,
TableName VARCHAR(50)NOT NULL,
Operation CHAR(1) NOT NULL,
PrimaryKey VARCHAR(50) NOT NULL,
-- RowDescription VARCHAR(50) NULL,
SecondaryRow VARCHAR(50) NULL,
[Column] VARCHAR(50) NOT NULL,
OldValue VARCHAR(50) NULL,
NewValue VARCHAR(50) NULL
) -
GO
-
-------------------------------------------------------------
-- Create function to simulate the Columns_Updated() value -
IF EXISTS (SELECT *
FROM sysobjects
WHERE NAME = 'GenColUpdated')
DROP FUNCTION GenColUpdated
Go -
CREATE FUNCTION dbo.GenColUpdated
(@Col INT,@ColTotal INT)
RETURNS INT
AS
BEGIN
-- copyright 2001 Paul Nielsen
-- This function simulates Columns_Updated()
DECLARE
@ColByte INT,
@ColTotalByte INT,
@ColBit INT -
-- Calculate Byte Positions
SET @ColTotalByte = 1 + ((@ColTotal-1) /8)
SET @ColByte = 1 + ((@Col-1)/8)
SET @ColBit = @col - ((@colByte-1) * 8) -
-- gen Columns_Updated() value for given column position
RETURN
POWER(2,@colbit + ((@ColTotalByte-@ColByte) * 8)-1)
END
go -
-------------------------------------------------------------
-- Create the Dynamic Audit Stored Procedures -
IF EXISTS (SELECT * FROM SysObjects WHERE NAME = 'pAudit')
DROP PROC pAudit
Go -
CREATE PROCEDURE pAudit (
@Col_Updated VARBINARY(1028),
@TableName VARCHAR(100),
@PrimaryKey SYSNAME)
AS
-- dynamic auto-audit trigger/stored procedure
-- copyright 2001 Paul Nielsen
SET NoCount ON
DECLARE
@ColTotal INT,
@ColCounter INT,
@ColUpdatedTemp INT,
@ColName SYSNAME,
@BlankString CHAR(1),
@sqlStr NVARCHAR(1000),
@ColNull NVARCHAR(50),
@SysUser NVARCHAR(100),
@ColumnDataType INT,
@IsUpdate BIT,
@tempError INT -
SET @SysUser = suser_sname()
SET @BlankString = '' -
-- Initialize Col variables
SELECT @ColCounter = 0
SELECT @ColTotal = Count(*)
FROM SysColumns
JOIN SysObjects
ON SysColumns.id = SysObjects.id
WHERE SysObjects.name = @TableName -
-- Set IsUpdated Flag
IF EXISTS(SELECT * FROM #tempDel)
SELECT @IsUpdate = 1
ELSE
SELECT @IsUpdate = 0 -
-- Column Updates
WHILE ((SELECT @ColCounter) != @ColTotal)
-- run through some columns
BEGIN
SELECT @ColCounter = @ColCounter + 1
SET @ColUpdatedTemp
= dbo.GenColUpdated(@ColCounter,@ColTotal) -
-- bitwise AND between updated bits
-- and the selected column bit
IF (@Col_Updated & @ColUpdatedTemp) = @ColUpdatedTemp
BEGIN
SET @ColNull = null
SELECT
@ColName = SysColumns.[name],
-- get the column name & Data Type
@ColumnDataType = SysColumns.xtype
FROM SysColumns
JOIN SysObjects
ON SysColumns.id = SysObjects.id
WHERE SysObjects.[NAME] = @TableName
and SysColumns.ColID = @ColCounter
IF @ColName NOT IN ('Created','Modified')
BEGIN
-- text columns
IF @ColumnDataType IN
( 175,239,99,231,35,98,167 )
SET @ColNull = ''''''
-- numeric + bit columns
ELSE IF @ColumnDataType IN
( 106,62,56,60,108,59,52,122,104 )
SET @ColNull = '0'
-- date columns
ELSE IF @ColumnDataType IN ( 61,58 )
SET @ColNull = '''1/1/1980'''
-- uniqueidentifier columns
ELSE IF @ColumnDataType IN ( 36 )
SET @ColNull = ''''''
IF @ColNull IS NOT NULL
BEGIN
IF @IsUpdate = 1
SET @sqlStr =
' Insert Audit(TableName,PrimaryKey,SysUser,[Column],'
+' AuditDate,Application,OldValue,NewValue,Operation)'
+' Select '''+ @TableName + ''',
#tempIn.['+ @PrimaryKey + '],
''' + @SysUser + ''',' +
'''' + @ColName + ''',GetDate(),App_Name(),' +
' IsNull(convert(nvarchar(100),
#tempDel.[' + @ColName + ']),''<null>''),
#tempIn.[' + @ColName + ']),''U''' +
' From #tempIn' +
' Join #tempDel' +
' On #tempIn.['+ @PrimaryKey + ']
= #tempDel.['+ @PrimaryKey + ']' +
' AND isnull(#tempIn.' + @ColName + ',' + @ColNull + ')
!= isnull(#tempDel.' + @ColName + ',' + @ColNull + ')'
+ ' Where Not (#tempIn.[' + @ColName + '] Is Null
and #tempDel.[' + @ColName + '] Is Null)'
ELSE -- Insert
SET @sqlStr =
' Insert Audit(TableName,'
+' AuditDate,Operation)'
+' Select '''+ @TableName + ''',#tempIn.['+ @PrimaryKey
+ '],''' + @SysUser + ''',' +
'''' + @ColName + ''',' +
' Null,' +
' IsNull(convert(nvarchar(100),
#tempIn.[' + @ColName +']),''I''' +
' From #tempIn' +
' Where Not (#tempIn.[' + @ColName + '] Is Null)' -
------------------------------------------------------------
------------------------------------------------------------
-- sample Table Triggers
-- this will need to be added to every table
-- and the Table and Primary Key settings -
-- Products trigger
-
IF EXISTS (SELECT *
FROM sysobjects
WHERE NAME = 'Products_Audit')
DROP TRIGGER Products_Audit
Go -
CREATE TRIGGER Products_Audit
ON dbo.Products
AFTER Insert,Update
NOT FOR REPLICATION
AS
-- Dynamic Audit Trail Code Begin
-- (c)2001 Paul Nielsen
DECLARE
@Col_Updated VARBINARY(1028),
@PrimaryKey SYSNAME -
SET NoCount ON
-
-- Set up the Audit data
-- set to the table name
SET @TableName = 'Products'
-- set to the column to identify the row
SET @PrimaryKey = 'ProductID'
SET @Col_Updated = Columns_Updated()
SELECT * INTO #TempIn FROM Inserted
SELECT * INTO #TempDel FROM Deleted -
-- call the audit stored procedure
EXEC pAudit @Col_Updated,@TableName,@PrimaryKey -
Go
-------------------------------------------------------------
-- Customer Trigger -
IF EXISTS (SELECT *
FROM SysObjects
WHERE [NAME] = 'Customers_Audit')
DROP TRIGGER Customers_Audit
Go -
CREATE TRIGGER Customers_Audit
ON dbo.Customers
AFTER Insert,Update
NOT FOR REPLICATION
AS
-- Dynamic Audit Trail
-- (c)2001 Paul Nielsen
DECLARE
@Col_Updated VARBINARY(1028),
@PrimaryKey SYSNAME
SET NoCount ON
SET @TableName = 'Customers'
SET @PrimaryKey = 'CustomerID'
SET @Col_Updated = Columns_Updated()
SELECT * INTO #TempIn FROM Inserted
SELECT * INTO #TempDel FROM Deleted
EXEC pAudit @Col_Updated,@PrimaryKey
go -
----------------------------------------------------
-- Sample test code -
-- test insert
INSERT Products (ProductName,CategoryID)
VALUES('Ye Old Audit Trail',1)
go -
-- test single row updates
UPDATE Products
SET ProductName = 'Audit Test'
WHERE ProductID = 1
go -
UPDATE Products
SET ReorderLevel = 3
WHERE ProductID = 1
go -
-- test multi-row update
UPDATE Products
SET UnitPrice = UnitPrice * 1.1
WHERE CategoryID = 1
go -
-- test all columns update
UPDATE Customers
SET
ContactName = 'Phil Senn',
CompanyName = 'AuditTest',
ContactTitle = 'M.P.',
Address = '123 Audit Ln. Pl. Ave. Dr.',
City = 'Hickory',
Region = 'NC',
PostalCode = '12345',
Country = 'US',
Phone = '555 123-4567',
Fax = '555 123-4568'
WHERE CustomerID = 'ALFKI'
go -
-
-- view Products w/ Audit SELECT Products.ProductName,Audit.* FROM Products JOIN Audit ON Audit.PrimaryKey = Products.ProductID WHERE Audit.TableName = 'Products'
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。