This is a modification to an earlier tip I wrote, whereas this code will only record delete changes, my earlier article will record delete and update changes to the data.
To view the original post from Brett Kaiser, please click here:Using SQL Server Management Studio express, open a new query window pointing towards your DB and start by creating a new table that will store all of the tables you wish to implement audit triggers for:
— CREATE A Driver Table for all Tables in your catalog you wish to audit
DECLARE
myCursor99 CURSOR
FOR
SELECT
TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
FROM tblAudit
DECLARE @TABLE_CATALOG sysname, @TABLE_SCHEMA sysname, @TABLE_NAME sysname, @COLUMN_NAMES varchar(MAX), @sql varchar(MAX)
SELECT @COLUMN_NAMES = ”
OPEN
myCursor99
FETCH
NEXT FROM myCursor99 INTO @TABLE_CATALOG, @TABLE_SCHEMA,@TABLE_NAME
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @SQL = ‘GRANT SELECT ON ‘ + @TABLE_CATALOG + ‘.’ +@TABLE_SCHEMA + ‘.’ + @TABLE_NAME + ‘_H TO PUBLIC’
SELECT SQL = @sql
EXEC(@SQL)
SELECT @SQL = ‘GRANT INSERT ON ‘ + @TABLE_CATALOG + ‘.’ + @TABLE_SCHEMA+ ‘.’ + @TABLE_NAME + ‘_H TO PUBLIC’
EXEC(@SQL)
FETCH NEXT FROM myCursor99 INTO @TABLE_CATALOG,@TABLE_SCHEMA, @TABLE_NAME
END
CLOSE myCursor99
DEALLOCATE myCursor99
GO
FOR
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME FROM tblAuditDECLARE @TABLE_CATALOG sysname, @TABLE_SCHEMA sysname, @TABLE_NAME sysname, @COLUMN_NAMES varchar(8000), @sql varchar(8000)
SELECT @COLUMN_NAMES = ”
OPEN myCursor99
FETCH NEXT FROM myCursor99 INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @COLUMN_NAMES = @COLUMN_NAMES + ‘, ‘ + COLUMN_NAME
FROM INFORMATION_SCHEMA.Columns
WHERE TABLE_CATALOG = @TABLE_CATALOG AND TABLE_SCHEMA = @TABLE_SCHEMA AND TABLE_NAME = @TABLE_NAME And DATA_TYPE <> ‘timestamp’
ORDER BY ORDINAL_POSITION
SELECT @SQL = ‘CREATE TRIGGER ‘ + @TABLE_SCHEMA + ‘_’ + @TABLE_NAME + ‘_TR ON ‘ + @TABLE_SCHEMA + ‘.’ +@TABLE_NAME
+ ‘ FOR DELETE AS ‘
+ ‘ DECLARE @HOSTNAME sysname, @DESC varchar(50) ‘
+ ‘ SELECT @HOSTNAME = hostname from master.dbo.sysprocesses where spid = @@SPID ‘
+ ‘ IF EXISTS(SELECT * FROM ‘ + @TABLE_NAME + ‘) SELECT @DESC = ‘
+ ”” + ”” + ‘ ELSE SELECT @DESC = ‘ + ”” + ‘MASS DELETE’ + ””
+ ‘ If Not Exists (Select * From Inserted) And Exists (Select * From Deleted) And @DESC = ”” ‘
+ ‘ INSERT INTO ‘ + @TABLE_NAME + ‘_H ( ‘
+ ‘ HIST_ADD_TYPE, HIST_ADD_SYSTEM_USER, HIST_ADD_USER_NAME, HIST_ADD_HOSTNAME, HIST_ADD_SPID, HIST_ADD_DESC’
+ @COLUMN_NAMES + ‘)’
+ ‘ SELECT ”D”, SYSTEM_USER, REPLACE (USER_NAME(),”DOMAINNAME”,””) , @HOSTNAME, @@SPID, @DESC’
+ @COLUMN_NAMES + ‘ FROM deleted’
+ ‘ If Not Exists (Select * From Inserted) And Exists (Select * From Deleted) And @DESC <> ”” ‘
+ ‘ INSERT INTO ‘ + @TABLE_NAME + ‘_H ( ‘
+ ‘ HIST_ADD_TYPE, HIST_ADD_SYSTEM_USER, HIST_ADD_USER_NAME, HIST_ADD_HOSTNAME, HIST_ADD_SPID, HIST_ADD_DESC’
+ @COLUMN_NAMES + ‘)’
+ ‘ SELECT TOP 1 ”D”, SYSTEM_USER, REPLACE(USER_NAME(),”DOMAINNAME”,””), @HOSTNAME, @@SPID, @DESC’
+ @COLUMN_NAMES + ‘ FROM deleted’
SELECT @sql = REPLACE(@SQL, ‘, Default ‘, ‘, [Default] ‘)
SELECT @sql = REPLACE(@SQL, ‘, Default) ‘, ‘, [Default]) ‘)
Print @SQL
Select TRIGGERSQL = @sql
EXEC(@SQL)
SELECT @SQL = ”, @COLUMN_NAMES = ”
FETCH NEXT FROM myCursor99 INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME
END
CLOSE myCursor99
DEALLOCATE myCursor99
GO
— *********** DROP TRIGGER CODE FOLLOWS ************