Skip to main content
Skip table of contents

How to align definitions with MS SQL Database trigger

PLEASE USE THIS WITH CARE and GOOD TESTS!

For a bavarian customer we moved from ORACLE to MS SQL SERVER. For security reasons we use two production databases.

Now the issue was, if a user creates or change a definition on one database the other side is not synced automatically for this request i have created a database trigger to align the two tables.

This trigger supports NEW entries, UPDATE from the NAME and the SOFTDELETE Flag. DELETE is not supported for security reasons. The BOLD marked variables need to be changed for your system.

SQL_DefinitionSynch_Prototype2.6.sql

SQL
USE [DigaSystemA]
GO
/****** Object: Trigger [david].[triggerUpdateDefinitions] Script Date: 06.03.2019 19:10:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [david].[triggerUpdateDefinitions]
 ON [david].[DEFINITION]
 FOR INSERT, UPDATE
AS
 IF TRIGGER_NESTLEVEL() != 1
 RETURN;
BEGIN
 DECLARE @databaseSource nvarchar(254); DECLARE @databaseDestination nvarchar(254); DECLARE @databaseLog nvarchar(254);
 DECLARE @version nvarchar(20) = '| Version: 2.6';
 SET @databaseSource = 'DigaSystemA';
 SET @databaseDestination = 'DigaSystemB';
 SET @databaseLog = '[TriggerLog].[dbo].[Log]';
/* helper variables for quotes */
 DECLARE @4Q nvarchar(4) = ''''; /* 4 quotes used at begin and end of variables */
 DECLARE @1Q char = CHAR(39); 
 
 /* section is the field section for that definition like the author has section nr. 29 */
 DECLARE @sectionOld int; DECLARE @sectionNew int;
 SELECT @sectionOld=del.SECTION from deleted del;
 SELECT @sectionNew=ins.SECTION from inserted ins;
/* this is the ref. number of the definition */
 DECLARE @definitionNrOld int; DECLARE @definitionNrNew int;
 SELECT @definitionNrOld=del.DEFNR from deleted del;
 SELECT @definitionNrNew=ins.DEFNR from inserted ins;
/* displayed name of the definition */
 DECLARE @definitionNameOld nvarchar(254); DECLARE @definitionNameNew nvarchar(254);
 SELECT @definitionNameOld=del.NAME from deleted del;

 SET @definitionNameOld = REPLACE(@definitionNameOld, @1Q, @1Q+@1Q); /* 
this is needed if the returned value has one ' for select and update two
 '' are needed */
 SELECT @definitionNameNew=ins.NAME from inserted ins;
 SET @definitionNameNew = REPLACE(@definitionNameNew, @1Q, @1Q+@1Q);
 
 /* flags 0 is normal, 1 is soft deleted */
 DECLARE @flagsOld int; DECLARE @flagsNew int;
 SELECT @flagsOld=del.FLAGS from deleted del;
 SELECT @flagsNew=ins.FLAGS from inserted ins;
/* variable for create a log entry */
 DECLARE @SqlLogCommand nvarchar(max);
 /* this is the highest definitiion ref. number */
 DECLARE @maxDefNr nvarchar(max);
/*
 count how many values found at the destination database 0 is good for 
new definitions, 1 for updated definitions - other than that = bad */
 DECLARE @countDestValuesFound int = -1;
 DECLARE @countDestValuesFoundParmDefinition nvarchar(max);
 DECLARE @SqlCommandCountDestValues nvarchar(max);
/* for UPDATE */
 IF EXISTS(SELECT * FROM deleted)
 BEGIN
 SET @countDestValuesFoundParmDefinition = N'@count int OUTPUT';
 SET @SqlCommandCountDestValues = N'SELECT @count = count(Name) from ' + @databaseDestination + N'.david.DEFINITION' +

 N' WHERE ' + @databaseDestination + N'.david.DEFINITION.SECTION = ' + 
cast(@sectionOld as nvarchar(max)) + N' AND ' + @databaseDestination + 
N'.david.DEFINITION.NAME = ' +@4Q+ @definitionNameOld +@4Q;
 EXECUTE sp_executesql @SqlCommandCountDestValues, @countDestValuesFoundParmDefinition, @count = @countDestValuesFound OUTPUT; 
 
 /* if more than one entry is found at destination something is wrong! (not allowed doublicates found) */
 IF @countDestValuesFound != 1
 BEGIN
 SET @SqlLogCommand =
 'INSERT INTO ' + @databaseLog + 

 ' VALUES (' +@4Q+ cast(cast(CURRENT_TIMESTAMP as datetime)as 
nvarchar(max)) +@4Q+ ',' +@4Q+ @databaseSource +@4Q+ ',' +@4Q+ 
@databaseDestination +@4Q+ ',' +@4Q+ @definitionNameOld +@4Q+ ',' +@4Q+ 
@definitionNameNew +@4Q+ ',' + cast(@flagsOld as nvarchar(max)) + ',' + 
cast(@flagsNew as nvarchar(max)) + ',' + cast(@sectionOld as 
nvarchar(max)) + ',' + cast(@sectionNew as nvarchar(max)) + ',' + 
cast(@definitionNrOld as nvarchar(max)) + ',' + cast(@definitionNrNew as
 nvarchar(max)) + ',' +
 +@4Q+ 'Warning: ' + 
cast(@countDestValuesFound as nvarchar(max)) + ' entries found at 
destination - no update of destination data (for security reasons)' 
+@4Q+ ')';
 EXECUTE (@SqlLogCommand)
 RETURN;
 END;
/* update changes if the trigger has a deleted result and the count at destination is 1 */
 IF @countDestValuesFound = 1 
 BEGIN
 declare @SqlUpdateDefinitionCommand nvarchar(max);
 set @SqlUpdateDefinitionCommand = 
 'UPDATE ' + @databaseDestination + '.david.DEFINITION' +
 ' SET NAME = ' +@4Q+ @definitionNameNew +@4Q+ ', FLAGS = ' + cast(@flagsNew as nvarchar(max)) +

 ' WHERE ' + @databaseDestination + '.david.DEFINITION.SECTION = ' + 
cast(@sectionOld as nvarchar(max)) + ' AND ' + @databaseDestination + 
'.david.DEFINITION.NAME = ' +@4Q+ @definitionNameOld +@4Q
 EXECUTE (@SqlUpdateDefinitionCommand)
set @SqlLogCommand =
 'INSERT INTO ' + @databaseLog + 

 ' VALUES (' +@4Q+ cast(cast(CURRENT_TIMESTAMP as datetime)as 
nvarchar(max)) +@4Q+ ',' +@4Q+ @databaseSource +@4Q+ ',' +@4Q+ 
@databaseDestination +@4Q+ ',' +@4Q+ @definitionNameOld +@4Q+ ',' +@4Q+ 
@definitionNameNew +@4Q+ ',' + cast(@flagsOld as nvarchar(max)) + ',' + 
cast(@flagsNew as nvarchar(max)) + ',' + cast(@sectionOld as 
nvarchar(max)) + ',' + cast(@sectionNew as nvarchar(max)) + ',' + 
cast(@definitionNrOld as nvarchar(max)) + ',' + cast(@definitionNrNew as
 nvarchar(max)) + ',' +
 +@4Q+ replace(@SqlUpdateDefinitionCommand + @version, '''', @4Q+@4Q) +@4Q+ ')';
 EXECUTE (@SqlLogCommand)
 RETURN;
 END;
 RETURN;
 END;
/* for INSERT */
 /* for new items no data from trigger "deleted" and no entry found at destination */
 IF NOT EXISTS(SELECT * FROM deleted)
 BEGIN
 SET @countDestValuesFoundParmDefinition = N'@count int OUTPUT';
 SET @SqlCommandCountDestValues = N'SELECT @count = count(Name) from ' + @databaseDestination + N'.david.DEFINITION' +

 N' WHERE ' + @databaseDestination + N'.david.DEFINITION.SECTION = ' + 
cast(@sectionNew as nvarchar(max)) + N' AND ' + @databaseDestination + 
N'.david.DEFINITION.NAME = ' +@4Q+ @definitionNameNew +@4Q;
 EXECUTE sp_executesql @SqlCommandCountDestValues, @countDestValuesFoundParmDefinition, @count = @countDestValuesFound OUTPUT;
 
 /* if more than one entry is found at destination something is wrong! (not allowed doublicates found) */
 IF @countDestValuesFound != 0
 BEGIN
 SET @SqlLogCommand =
 'INSERT INTO ' + @databaseLog + 

 ' VALUES (' +@4Q+ cast(cast(CURRENT_TIMESTAMP as datetime)as 
nvarchar(max)) +@4Q+ ',' +@4Q+ @databaseSource +@4Q+ ',' +@4Q+ 
@databaseDestination +@4Q+ ',' +@4Q+ 'NULL' +@4Q+ ',' +@4Q+ 
@definitionNameNew +@4Q+ ',' + 'NULL' + ',' + cast(@flagsNew as 
nvarchar(max)) + ',' + 'NULL' + ',' + cast(@sectionNew as nvarchar(max))
 + ',' + 'NULL' + ',' + cast(@definitionNrNew as nvarchar(max)) + ',' +

 +@4Q+ 'Info: ' + cast(@countDestValuesFound as nvarchar(max)) + ' 
entries found at destination - no update of destination data needed 
(entry already exists)' +@4Q+ ')';
 EXECUTE (@SqlLogCommand)
 RETURN;
 END; 
 
 /* if more than one entry is found at destination something is wrong! (not allowed duplicates found) */
 IF @countDestValuesFound = 0
 BEGIN
 /* first update (+1) last primary key from DIGAS Table */
 DECLARE @SqlUpdateLastNumberCommand nvarchar(max);
 SET @SqlUpdateLastNumberCommand = 
 'UPDATE ' + @databaseDestination + '.david.DIGAS' +
 ' SET LASTPRIMARYKEY=LASTPRIMARYKEY+1' +
 ' WHERE TABLENAME=N' + +@4Q+ 'DEFINITION' +@4Q
 EXECUTE (@SqlUpdateLastNumberCommand)
/* then get last primary key from DIGAS Table */
 declare @SqlGeltLastPrimaryKeyCommand nvarchar(max);

 SET @SqlGeltLastPrimaryKeyCommand = N'SELECT @lastPrimaryKeyOut = 
LASTPRIMARYKEY FROM ' + @databaseDestination + '.david.DIGAS' + ' WHERE 
TABLENAME = N' +@4Q+ 'DEFINITION' +@4Q
 declare @parmDefinition2 nvarchar(max);
 SET @parmDefinition2 = N'@lastPrimaryKeyOut int OUTPUT'
 EXECUTE sp_executesql @SqlGeltLastPrimaryKeyCommand, @parmDefinition2, @lastPrimaryKeyOut = @maxDefNr OUTPUT;
 
 /* insert now the new definition with the new primary key number*/
 declare @SqlInsertDefinitionCommand nvarchar(max);
 set @SqlInsertDefinitionCommand = 
 'INSERT INTO ' + @databaseDestination + '.david.DEFINITION' +

 ' VALUES (' + cast(@maxDefNr as nvarchar(max)) + ', ' + 
cast(@sectionNew as nvarchar(max)) + ', ' + cast(@flagsNew as 
nvarchar(max)) + ' ,' +@4Q+ @definitionNameNew +@4Q+ ')';
 EXECUTE (@SqlInsertDefinitionCommand)
/* update (+1) the change number in the DIGAS table*/
 declare @SqlUpdateChangeNumberCommand nvarchar(max);
 set @SqlUpdateChangeNumberCommand = 
 'UPDATE ' + @databaseDestination + '.david.DIGAS' +
 ' SET CHANGENUMBER=CHANGENUMBER+1' +
 ' WHERE TABLENAME=N' + +@4Q+ 'DEFINITION' +@4Q
 EXECUTE (@SqlUpdateChangeNumberCommand)
/* write to log */
 set @SqlLogCommand =
 'INSERT INTO ' + @databaseLog + 

 ' VALUES (' +@4Q+ cast(cast(CURRENT_TIMESTAMP as datetime)as 
nvarchar(max)) +@4Q+ ',' +@4Q+ @databaseSource +@4Q+ ',' +@4Q+ 
@databaseDestination +@4Q+ ',' +@4Q+ 'NULL' +@4Q+ ',' +@4Q+ 
@definitionNameNew +@4Q+ ',' + 'NULL' + ',' + cast(@flagsNew as 
nvarchar(max)) + ',' + 'NULL' + ',' + cast(@sectionNew as nvarchar(max))
 + ',' + 'NULL' + ',' + cast(@definitionNrNew as nvarchar(max)) + ',' +

 +@4Q+ 'InsertNewDefinition: >>' + 
replace(@SqlUpdateLastNumberCommand + ' >> ' + 
@SqlInsertDefinitionCommand + ' >> ' + 
@SqlUpdateChangeNumberCommand, '''', @4Q+@4Q) +@4Q+ ')';
 EXECUTE (@SqlLogCommand) 
 END;
 END;
END;

Logging:

Create a extra database for logging - SQL_DefinitionSynch_createLogTable.sql

Example:

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.