Database updates can be monitored by using INSERT,DELETE,UPDATE triggers on tables to be monitored, to add update details to a log table.
The SISfm user name can be included in logged update details by setting DbUpdateLogging to TRUE.
Here are examples of the triggers and stored procedures required to log updates in table sisfm_db_update_log:
The following procedure can be called by any INSERT,DELETE,UPDATE trigger as shown after it.
CREATE PROCEDURE sisfm_db_update_logger @tableName VARCHAR(50), @columnsUpdated VARBINARY(MAX) AS BEGIN SET NOCOUNT ON; DECLARE @UserID VARCHAR(50) = UPPER(CONVERT(VARCHAR(50), SESSION_CONTEXT(N'UserID'))); IF @UserID IS NULL RETURN; DECLARE @PK VARCHAR(8000) = ''; DECLARE curPK CURSOR LOCAL FOR SELECT RTRIM(field_name) FROM sisfm_flds WHERE table_name=@tableName AND primary_key>0 ORDER BY primary_key; OPEN curPK; WHILE 1=1 BEGIN DECLARE @fieldName VARCHAR(50); FETCH NEXT FROM curPK INTO @fieldName; IF @@FETCH_STATUS <> 0 BREAK; IF @PK <> '' SET @PK = @PK + '+''~''+'; SET @PK = @PK + 'RTRIM(CONVERT(VARCHAR(50), i.' + @fieldName + '))'; END CLOSE curPK; IF @PK = '' RETURN; DECLARE @query NVARCHAR(4000); IF EXISTS(SELECT * FROM #tempDeleted) AND EXISTS(SELECT * FROM #tempInserted) BEGIN DECLARE curColumnUpdated CURSOR LOCAL FOR SELECT name FROM syscolumns WHERE id = OBJECT_ID(@tableName) AND CONVERT(VARBINARY,REVERSE(@columnsUpdated)) & POWER(CONVERT(BIGINT, 2), colorder - 1) > 0; OPEN curColumnUpdated; WHILE 1=1 BEGIN DECLARE @columnUpdated VARCHAR(50); FETCH NEXT FROM curColumnUpdated INTO @columnUpdated; IF @@FETCH_STATUS <> 0 BREAK; SET @query = 'SELECT GETDATE(),''' + @UserID + ''',''' + @tableName + ''',' + @PK + ',''UPDATE'',' + '''' + @columnUpdated + ''',' + 'd.' + @columnUpdated + ',' + 'i.' + @columnUpdated + ' FROM #tempInserted i' + ' INNER JOIN #tempDeleted d ON ' + @PK + '=' + REPLACE(@PK,'i.','d.') + ' WHERE d.' + @columnUpdated + '!=i.'+@columnUpdated + ' OR d.' + @columnUpdated + ' IS NULL AND i.'+@columnUpdated + ' IS NOT NULL' + ' OR i.' + @columnUpdated + ' IS NULL AND d.'+@columnUpdated + ' IS NOT NULL'; INSERT INTO sisfm_db_update_log (date_time, user_name, table_name, primary_key, update_action , field_name, field_value_old, field_value_new) EXEC sp_executesql @query; END; CLOSE curColumnUpdated; END ELSE IF EXISTS(SELECT * FROM #tempDeleted) BEGIN SET @query = 'SELECT GETDATE(),''' + @UserID + ''',''' + @tableName + ''',' + @PK + ',''DELETE'' FROM #tempDeleted i'; INSERT INTO sisfm_db_update_log (date_time, user_name, table_name, primary_key, update_action ) EXEC sp_executesql @query; END ELSE BEGIN SET @query = 'SELECT GETDATE(),''' + @UserID + ''',''' + @tableName + ''',' + @PK + ',''INSERT'' FROM #tempInserted i'; INSERT INTO sisfm_db_update_log (date_time, user_name, table_name, primary_key, update_action ) EXEC sp_executesql @query; END
The following creates a trigger for table rm which calls this stored procedure:
CREATE TRIGGER TR_rm ON rm AFTER INSERT,DELETE,UPDATE AS BEGIN SELECT * INTO #tempInserted FROM INSERTED; SELECT * INTO #tempDeleted FROM DELETED; DECLARE @tableName VARCHAR(50); SELECT @tableName = OBJECT_NAME(parent_obj) FROM SYSOBJECTS WHERE id=@@PROCID; DECLARE @columnsUpdated VARBINARY(MAX) = COLUMNS_UPDATED(); EXEC sisfm_db_update_logger @tableName, @columnsUpdated DROP TABLE #tempInserted; DROP TABLE #tempDeleted; END
If you need further assistance, please contact IFM Support <support@integratedfm.com.au>.