Solved

Help in writing trigger

Posted on 2014-03-20
4
389 Views
Last Modified: 2014-04-03
Hi I have two tables.

Table1
Client_ID int Identity    (PK)

ClientName Varchar(50)
gender Bit
Address varchar(300)
Status char(1)

and a Log table

Table_History

History_ID int Identity(1,1) (PK)

User_ID   int
FieldEffected varchar
Olddata varchar
newdata varchar
timestamp datetime

can any one help me in writing trigger for Insert , Update and delete . for timebeing I can fix user_ID as '1000001'
0
Comment
Question by:Vikash p
  • 2
4 Comments
 
LVL 32

Accepted Solution

by:
bhess1 earned 167 total points
ID: 39944035
In this case, you would do better with three triggers rather than only one.

On your AFTER INSERT trigger, you know every column was changed.  You have the option of logging each item into the table separately, or entering a special row where FieldEffected could equal INSERT, ALL (INSERT), or some other specific value you choose.  OldData would be NULL, and newData would be something like:

Cast(@@Identity as varchar(10) ) + '|' + IsNull(i.ClientName, '') + '|' + Cast(i.gender as char(1)) + '|' + ....  Until you have all of the fields appended into one string.  This is simple.  However, having one item per field is cleaner, so you may decide to simply explicitly code each separate insert into the trigger.  An almost identical procedure could be created for a AFTER DELETE trigger as well.

It only gets complex on an update trigger.

There are various ways that you could try to automate the trigger so that you would always include each field in the table.  Iterating through the correct system view would let you automatically generate the INSERT statements.  However, for this example, I am assuming fixed code for the query.

There are two primary ways to identify if a column has changed (three, if you count a direct compare between INSERTED and DELETED).  The simplest to understand is the UPDATE() function, e.g.

IF UPDATE(ClientName)
... add logging code here ...

IF UPDATE(Gender)
....

Note that the documentation indicates that UPDATE() will return TRUE even if the update failed (that is, nothing changed).

There is also the COLUMNS_UPDATED() function, that returns a bit pattern indicating which columns changed (if any). This returns a VARBINARY containing enough bits so that there is one bit per column in the table.  If you performed an UPDATE on the sample table snippet:


Client_ID int Identity    (PK)
ClientName Varchar(50)
gender Bit
Address varchar(300)
Status char(1)

You would get a bit pattern like:

000 -- There are only five fields, so the last three bits per byte are useless
0     -- Status not updated
1     -- address updated
0     -- gender not updated
1     -- Client Name updated
0     -- Normally, you will not be updating the ID

However you determine it, when you identify the changed columns, you then do a simple INSERT into your log with the appropriate data.
0
 
LVL 75

Assisted Solution

by:Anthony Perkins
Anthony Perkins earned 333 total points
ID: 39944050
You may want to rethink the design.  However if that is not an option then something like this should do it:
CREATE TRIGGER trg_YourTrigger ON Table1 
	AFTER INSERT, UPDATE, DELETE 

AS

BEGIN

IF UPDATE(ClientName)
	INSERT Table_History ([User_ID], FieldEffected, Olddata, newdata, [timestamp])
	SELECT  '1000001', 'ClientName', d.ClientName, i.ClientName, GETDATE()
	FROM	DELETED d
			FULL OUTER JOIN INSERTED i ON d.Client_ID = i.Client_ID
	WHERE	d.Client_ID IS NULL				-- INSERT
			OR i.Client_ID IS NULL			-- DELETE
			OR d.ClientName <> i.ClientName	-- UPDATE and the values changed

IF UPDATE(gender)
	INSERT Table_History ([User_ID], FieldEffected, Olddata, newdata, [timestamp])
	SELECT  '1000001', 'gender', d.gender, i.gender, GETDATE()
	FROM	DELETED d
			FULL OUTER JOIN INSERTED i ON d.Client_ID = i.Client_ID
	WHERE	d.Client_ID IS NULL				-- INSERT
			OR i.Client_ID IS NULL			-- DELETE
			OR d.gender <> i.gender			-- UPDATE and the values changed

IF UPDATE([Address])
	INSERT Table_History ([User_ID], FieldEffected, Olddata, newdata, [timestamp])
	SELECT  '1000001', 'Address', d.[Address], i.[Address], GETDATE()
	FROM	DELETED d
			FULL OUTER JOIN INSERTED i ON d.Client_ID = i.Client_ID
	WHERE	d.Client_ID IS NULL				-- INSERT
			OR i.Client_ID IS NULL			-- DELETE
			OR d.[Address] <> i.[Address]	-- UPDATE and the values changed

IF UPDATE([Status])
	INSERT Table_History ([User_ID], FieldEffected, Olddata, newdata, [timestamp])
	SELECT  '1000001', 'Status', d.[Status], i.[Status], GETDATE()
	FROM	DELETED d
			FULL OUTER JOIN INSERTED i ON d.Client_ID = i.Client_ID
	WHERE	d.Client_ID IS NULL				-- INSERT
			OR i.Client_ID IS NULL			-- DELETE
			OR d.[Status] <> i.[Status]		-- UPDATE and the values changed
END

Open in new window

0
 
LVL 75

Assisted Solution

by:Anthony Perkins
Anthony Perkins earned 333 total points
ID: 39944058
Note that the documentation indicates that UPDATE() will return TRUE even if the update failed (that is, nothing changed).
It will always be true if the column participated in an UPDATE statement, regardless of whether the value changed or not.  So really the only way to truly know if the value changed is to compare the values in Deleted and Inserted.
0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 39945218
When you compare the old and new values, you also need to compare correctly to allow NULL value(s) to be on one side or the other or both.
0

Featured Post

Back Up Your Microsoft Windows Server®

Back up all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Import New Records From Access Table To SQL Database Table 7 33
Acces SQL Insert Problem 6 32
SQL Syntax Grouping Sum question 7 27
MS SQL + date 6 23
Occasionally there is a need to clean table columns, especially if you have inherited legacy data. There are obviously many ways to accomplish that, including elaborate UPDATE queries with anywhere from one to numerous REPLACE functions (even within…
In this article I will describe the Copy Database Wizard method as one possible migration process and I will add the extra tasks needed for an upgrade when and where is applied so it will cover all.
Via a live example, show how to shrink a transaction log file down to a reasonable size.
Viewers will learn how to use the INSERT statement to insert data into their tables. It will also introduce the NULL statement, to show them what happens when no value is giving for any given column.

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question