The Code Slinger

February 11, 2011

Auto Generate History Table and Corresponding Trigger (SQL)

Filed under: SQL 2008 — Pete @ 12:54 pm
Tags: , ,

Extending the excellent work of this post by Bryan Massey, I’ve updated the script to replace the deprecated SysProperties table in lieu of the sys.extended_properties so that this procedure will operate in SQL 2008.  Enjoy!

/************************************************************************************************************
Created By:  Bryan Massey
Created On:  3/11/2007
Modified By: Peter Samwel
Modified On: 2/11/2011 — Updated SysProperties table refs (deprecated) to use the new (2008) extended_properties view.
Comments:  Stored proc performs the following actions:
1) Queries system tables to retrieve table schema for @TableName parameter
2) Creates a History table (“History_” + @TableName) to mimic the original table, plus include
additional history columns.
3) If @CreateTrigger = ‘Y’ then it creates an Update/Delete trigger on the @TableName table,
which is used to populate the History table.
******************************************* MODIFICATIONS **************************************************
MM/DD/YYYY – Modified By – Description of Changes
************************************************************************************************************/
CREATE PROCEDURE [dbo].[History_Bat_AutoGenerateHistoryTableAndTrigger]
@TableName VARCHAR(200),
@CreateTrigger CHAR(1) = ‘Y’ — optional parameter; defaults to “Y”
AS

DECLARE @SQLTable VARCHAR(8000), @SQLTrigger VARCHAR(8000), @FieldList VARCHAR(6000), @FirstField VARCHAR(200)
DECLARE @TAB CHAR(1), @CRLF CHAR(1), @SQL VARCHAR(1000), @Date VARCHAR(12)

SET @TAB = CHAR(9)
SET @CRLF = CHAR(13) + CHAR(10)
SET @Date = CONVERT(VARCHAR(12), GETDATE(), 101)
SET @FieldList = ”
SET @SQLTable = ”

DECLARE @TableDescr VARCHAR(500), @FieldName VARCHAR(100), @DataType VARCHAR(50)
DECLARE @FieldLength VARCHAR(10), @Precision VARCHAR(10), @Scale VARCHAR(10),  @FieldDescr VARCHAR(500), @AllowNulls VARCHAR(1)

DECLARE CurHistoryTable CURSOR FOR

— query system tables to get table schema
SELECT CONVERT(VARCHAR(500), SP2.value) AS TableDescription,
CONVERT(VARCHAR(100), SC.Name) AS FieldName, CONVERT(VARCHAR(50), ST.Name) AS DataType,
CONVERT(VARCHAR(10),SC.length) AS FieldLength, CONVERT(VARCHAR(10), SC.XPrec) AS FieldPrecision,
CONVERT(VARCHAR(10), SC.XScale) AS FieldScale,
CASE SC.IsNullable WHEN 1 THEN ‘Y’ ELSE ‘N’ END AS AllowNulls
FROM SysObjects SO
INNER JOIN SysColumns SC ON SO.ID = SC.ID
INNER JOIN SysTypes ST ON SC.xtype = ST.xtype
LEFT OUTER JOIN sys.extended_properties SP ON SC.ID = SP.major_id AND SC.ColID = SP.minor_id
LEFT OUTER JOIN sys.extended_properties SP2 ON SC.ID = SP2.major_id AND SP2.minor_id = 0
WHERE SO.xtype = ‘u’ AND SO.Name = @TableName
ORDER BY SO.[name], SC.ColOrder

OPEN CurHistoryTable

FETCH NEXT FROM CurHistoryTable INTO @TableDescr, @FieldName, @DataType,
@FieldLength, @Precision, @Scale, @AllowNulls

WHILE @@FETCH_STATUS = 0
BEGIN

— create list of table columns
IF LEN(@FieldList) = 0
BEGIN
SET @FieldList = @FieldName
SET @FirstField = @FieldName
END
ELSE
BEGIN
SET @FieldList = @FieldList + ‘, ‘ + @FieldName
END

IF LEN(@SQLTable) = 0
BEGIN
SET @SQLTable = ‘CREATE TABLE [DBO].[History_’ + @TableName + ‘] (‘ + @CRLF
SET @SQLTable = @SQLTable + @TAB + ‘[History’ + @FieldName + ‘] [INT] IDENTITY(1,1) NOT NULL,’ + @CRLF
END

SET @SQLTable = @SQLTable + @TAB + ‘[‘ + @FieldName + ‘] ‘ + ‘[‘ + @DataType + ‘]’
IF UPPER(@DataType) IN (‘CHAR’, ‘VARCHAR’, ‘NCHAR’, ‘NVARCHAR’, ‘BINARY’)
BEGIN
SET @SQLTable = @SQLTable + ‘(‘ + @FieldLength + ‘)’
END
ELSE IF UPPER(@DataType) IN (‘DECIMAL’, ‘NUMERIC’)
BEGIN
SET @SQLTable = @SQLTable + ‘(‘ + @Precision + ‘, ‘ + @Scale + ‘)’
END

IF @AllowNulls = ‘Y’
BEGIN
SET @SQLTable = @SQLTable + ‘ NULL’
END
ELSE
BEGIN
SET @SQLTable = @SQLTable + ‘ NOT NULL’
END

SET @SQLTable = @SQLTable + ‘,’ + @CRLF

FETCH NEXT FROM CurHistoryTable INTO @TableDescr, @FieldName, @DataType,
@FieldLength, @Precision, @Scale, @AllowNulls
END

CLOSE CurHistoryTable
DEALLOCATE CurHistoryTable

— finish history table script with standard history columns
SET @SQLTable = @SQLTable + @TAB + ‘[HistoryCreatedOn] [DATETIME] NULL,’ + @CRLF
SET @SQLTable = @SQLTable + @TAB + ‘[HistoryCreatedByUserID] [SMALLINT] NULL,’ + @CRLF

SET @SQLTable = @SQLTable + @TAB + ‘[HistoryCreatedByUserName] [VARCHAR](30) NULL,’ + @CRLF
SET @SQLTable = @SQLTable + @TAB + ‘[HistoryAction] [CHAR](1) NOT NULL’ + @CRLF
SET @SQLTable = @SQLTable + ‘ )’

PRINT @SQLTable

— execute sql script to create history table
EXEC(@SQLTable)

IF @@ERROR <> 0
BEGIN
PRINT ‘******************** ERROR CREATING HISTORY TABLE FOR TABLE: ‘ + @TableName + ‘ **************************************’
RETURN -1
END

IF @CreateTrigger = ‘Y’
BEGIN
— create history trigger
SET @SQLTrigger = ‘/************************************************************************************************************’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘Created By: ‘ + SUSER_SNAME() + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘Created On: ‘ + @Date + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘Comments: Auto generated trigger’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘***********************************************************************************************/’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘CREATE TRIGGER [Trigger_’ + @TableName + ‘_UpdateDelete] ON DBO.’ + @TableName + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘FOR UPDATE, DELETE’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘AS’ + @CRLF + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘DECLARE @Action CHAR(1)’ + @CRLF + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘IF EXISTS (SELECT ‘ + @FirstField + ‘ FROM Inserted)’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘BEGIN’ + @CRLF
SET @SQLTrigger = @SQLTrigger + @TAB + ‘SET @Action = ”U”’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘END’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘ELSE’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘BEGIN’ + @CRLF
SET @SQLTrigger = @SQLTrigger + @TAB + ‘SET @Action = ”D”’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘END’ + @CRLF + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘INSERT INTO History_’ + @TableName + @CRLF
SET @SQLTrigger = @SQLTrigger + @TAB + ‘(‘ + @FieldList + ‘, HistoryCreatedOn, HistoryCreatedByUserName, HistoryAction)’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘SELECT ‘ + @FieldList + ‘, GETDATE(), SUSER_SNAME(), @Action’ + @CRLF
SET @SQLTrigger = @SQLTrigger + ‘FROM DELETED’
–PRINT @SQLTrigger
— execute sql script to create update/delete trigger
EXEC(@SQLTrigger)

IF @@ERROR <> 0
BEGIN
PRINT ‘******************** ERROR CREATING HISTORY TRIGGER FOR TABLE: ‘ + @TableName + ‘ **************************************’
RETURN -1
END

END

Blog at WordPress.com.