First Post in this series: SQL Advent Calendar 2013-Day 1- Placeholders in SQL Prompt Snippets
As I was hanging our family Advent Calendar up, I thought I would make one for you, my readers. I’ll be sharing my scripts from two of my favorite products as well as tips on how to create your own.
The Final Piece
The last couple of days I’ve written here and here about how to add simple auditing to your tables using ER Studio Data Architect. Today is the finishing piece. Today I will share my SQL Prompt script that creates the triggers for the tables with the ModifiedBy and ModifiedDTS fields.
The trigger is an update trigger. Whenever the record is change, the trigger will be executed. If the user provided a value for the ModifieidBy field, then that value will be used. If a new value is not provided, then the SUSER_NAME() function will be used. I put that check in there for applications that use a single credential to log in to SQL Server, but the application can send in the actually user. If you don’t need that feature, then it can be taken out.
Before running the code, do the following.
- Use CTRL+SHIFT+M to update the script with the values you need. This will include a comma delimited list of table names, and a single schema name. (Eventually, I’ll add functionality for multiple schemas.)
- The script is setup to print the triggers to the Messages pane. You can copy the scripts into another window to execute, or you can set the @ReadyToExecute bit to 1. This will cause the scripts to be executed as the triggers are built.
WARNING: Make sure you verify that a trigger with the same name as the one being generated does not exists. IT WILL BE DROPPED with this code. ALSO, make sure adding this trigger, will not cause issues with other existing update triggers. |
USE
GO
/* ***********************************************************************************
Purpose: Creates new update triggers for tables that use ModifiedDTS and ModifiedBy.
Notes: 1. Use Shift + Ctrl + M to set Template Parameters
2. Change the @ReadyToexecute bit to 1, when you are ready to execute the
code, or simply run the sqcript that is generated in the Messages pane.
WARNING: Make sure you verify that a trigger with the same name as the one being
generated does not exists. IT WILL BE DROPPED with this code. ALSO, make
sure adding this trigger, will not cause issues with other existing
update trigers.
Author: Mickey Stuewe, www.mickeystuewe.com
Date: 12/10/2013
Revision History
(Change Date) (Author) (Description of Change)
-----------------------------------------------------------------
************************************************************************************ */
DECLARE
@ReadyToExecute AS bit = 1
DECLARE
@Tables AS nvarchar(max) = ''
,@SchemaName AS nvarchar(50) = '<schema,string,>'
,@TriggerName AS nvarchar(200)
,@TableName AS nvarchar(126)
,@SQL AS nvarchar(MAX)
,@PrimaryKeys_t_to_d AS nvarchar(MAX)
,@PrimaryKeys_d_to_i AS nvarchar(MAX)
DECLARE Trig_Cursor CURSOR
FOR
WITH cte_Pieces
AS
(
SELECT
1 AS ID
,1 AS StartString
,CONVERT(int,CHARINDEX(',', @Tables)) AS StopString
UNION ALL
SELECT
ID + 1 AS ID
,StopString + 1 AS StartString
,CONVERT(int,CHARINDEX(',', @Tables, StopString + 1)) AS StopString
FROM
cte_Pieces
WHERE
StopString > 0
)
,cte_Tables
AS
(
SELECT
SUBSTRING(@Tables, StartString, CASE WHEN StopString > 0 THEN StopString - StartString
ELSE LEN(@Tables)
END) AS TableName
FROM
cte_Pieces
)
SELECT
TableName
,'trg_' + TableName + '_u' AS TriggerName
FROM
cte_Tables
OPEN Trig_Cursor
FETCH NEXT FROM Trig_Cursor
INTO
@TableName
,@TriggerName
WHILE @@FETCH_STATUS = 0
BEGIN
--Get all the primary keys
SET @PrimaryKeys_t_to_d = NULL
SET @PrimaryKeys_d_to_i = NULL
SELECT
@PrimaryKeys_t_to_d = ISNULL(@PrimaryKeys_t_to_d + SPACE(36) + 'AND ','') + 't.' + KCU.COLUMN_NAME + ' = d.' + KCU.COLUMN_NAME + CHAR(13) + CHAR(10)
,@PrimaryKeys_d_to_i = ISNULL(@PrimaryKeys_d_to_i + SPACE(36) + 'AND ','') + 'd.' + KCU.COLUMN_NAME + ' = i.' + KCU.COLUMN_NAME + CHAR(13) + CHAR(10)
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC ON KCU.CONSTRAINT_CATALOG = TC.CONSTRAINT_CATALOG
AND KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
AND KCU.CONSTRAINT_SCHEMA = TC.CONSTRAINT_SCHEMA
WHERE
tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND KCU.TABLE_NAME = @TableName
AND KCU.CONSTRAINT_SCHEMA = @SchemaName
ORDER BY
KCU.ORDINAL_POSITION ASC
--Drop existing Trigger
SET @SQL = ''
SET @SQL = @SQL + N'IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N''[' + @SchemaName + '].[' + @TriggerName + ']''))' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'DROP TRIGGER ' + @SchemaName + '.' + @TriggerName + CHAR(13) + CHAR(10)
--PRINT @SQL
EXECUTE sp_executesql @SQL
--CREATE New Trigger
SET @SQL = N''
SET @SQL = @SQL + N'/* ********************************************************************************' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'Template: Created with template by Mickey Stuewe, www.mickeytsuewe.com' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'Purpose: Set ModifiedDTS and ModifiedBy columns.' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'Notes: ModifiedBy and ModifiedDTS will only changed if they were not changed' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' by the user.' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'Author: $USER$' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'Date: $DATE$' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'Revision History' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'(Change Date) (Author) (Description of Change)' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'-----------------------------------------------------------------' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' *********************************************************************************/' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'CREATE TRIGGER ' + @SchemaName + '.' + @TriggerName + + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' ON ' + @SchemaName + '.' + @TableName + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' AFTER UPDATE' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'AS ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'BEGIN' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' SET NOCOUNT ON' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' -- Update the ModifiedDTS/By fields if they are not passed in. ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' UPDATE ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' ' + @SchemaName + '.' + @TableName + + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' SET ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' ModifiedBy = CASE ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' WHEN i.ModifiedBy IS NULL THEN SUSER_NAME() ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' WHEN i.ModifiedBy <> d.ModifiedBy THEN i.ModifiedBy ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' WHEN ISNULL(i.ModifiedDTS,d.ModifiedDTS) = d.ModifiedDTS THEN SUSER_NAME() ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' ELSE i.ModifiedBy ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' END ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' ,ModifiedDTS = GETDATE() ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' FROM ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' ' + @SchemaName + '.' + @TableName + ' AS t ' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' INNER JOIN deleted AS d ON ' + @PrimaryKeys_t_to_d
SET @SQL = @SQL + N' INNER JOIN inserted AS i ON ' + @PrimaryKeys_d_to_i + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N' SET NOCOUNT OFF' + CHAR(13) + CHAR(10)
SET @SQL = @SQL + N'END ' + CHAR(13) + CHAR(10)
IF @ReadyToExecute = 0
BEGIN
SET @SQL = @SQL + N'GO ' + CHAR(13) + CHAR(10)
PRINT @SQL
END
ELSE
BEGIN
EXECUTE sp_executesql @SQL
END
IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[' + @SchemaName + '].[' + @TriggerName + ']'))
PRINT '--CREATED TRIGGER ' + @SchemaName + '.' + @TriggerName
ELSE
PRINT '--*** TRIGGER ' + @SchemaName + '.' + @TriggerName + ' was not created.***'
FETCH NEXT FROM Trig_Cursor
INTO
@TableName
,@TriggerName
END
CLOSE Trig_Cursor
DEALLOCATE Trig_Cursor
GO
Here is an example of what the trigger will look like. This example has a three part primary key.
Previous Post In Series: SQL Advent Calendar 2013 – Day 9 – Creating Change Tracking Fields (2 of 3)
Like this:
Like Loading...