Sql Triggers-Implementation Issue

Multi tool use
Sql Triggers-Implementation Issue
Hi guys i am making 2 tables for implementing triggers--
create table emp(id int primary key identity(1,1),
name char(40),
salary varchar(50),
gender char(40),
departmentid int);
insert into emp(name,salary,gender,departmentid) values ('jimmi',4800,'Male',4);
create table emp_audit
(
id int primary key identity(1,1),
audit varchar(60)
);
alter trigger trigger_em_update on emp for update
as begin
Declare @Id int
Declare @oldname char(40),@newname char(40)
Declare @oldsal int,@newsal int
Declare @oldgen char(40),@newgen char(40)
Declare @olddeptid int,@newdeptid int
Declare @auditstring nvarchar(max)
--select * from deleted;
select * into #temptable from inserted;
while(Exists(select id from #temptable)) --boolean condition if there are rows are not
Begin
set @auditstring =''
--if there are many rows we still select the first one
select Top 1 @Id =id,@newname=name,@newgen=gender,@newsal=salary,@newdeptid=departmentid
from #temptable;
select Top 1 @Id =id,@oldname=name,@oldgen=gender,@oldsal=salary,@olddeptid=departmentid
from deleted where @Id=id;
set @auditstring=' Employee with id= '+CAST(@Id as varchar(20))+ ' changed '
if(@oldname<>@newname)
set @auditstring=@auditstring + 'name from '+ @oldname +' to' +@newname
if(@oldsal<>@newsal)
set @auditstring=@auditstring + ' salary from '+ @oldsal +' to ' +@newsal
if(@oldgen<>@newgen)
set @auditstring=@auditstring + ' gender from ' + @oldgen + ' to ' + @newgen
-- if(@olddeptid<>@newdeptid)
--set @auditstring=@auditstring + ' departmentid from ' + cast(@olddeptid as nvarchar(5))+' to '
insert into emp_audit values(@auditstring)
delete from #temptable where id=@Id
end
end
when i use update query
update emp set name='vishi',gender='male',salary='4000',departmentid=3 where id=3;
It gives an error
"Conversion failed when converting the nvarchar value ' Employee with id= 3 changed name from james tovishi salary from ' to data type int.
"
i don't know how to solve this..can you solve this..
In
emp
you declare salary varchar(50)
, but in the trigger Declare @oldsal int,@newsal int
. You ought to decide on a single datatype. Adding quotes around values makes interpreting the audit easier, e.g. from 'Foo ' to 'Foo'
. As mentioned here: "Logging triggers should always be set to fire last. Otherwise, a subsequent trigger may rollback the original transaction, but the log table will have already been updated. This is a confusing state of affairs."– HABO
Jul 1 at 15:44
emp
salary varchar(50)
Declare @oldsal int,@newsal int
from 'Foo ' to 'Foo'
3 Answers
3
The problem is in line:
if(@oldsal<>@newsal)
set @auditstring=@auditstring + ' salary from '+ @oldsal +' to ' +@newsal
Should be:
if(@oldsal<>@newsal)
set @auditstring=@auditstring+ ' salary from '+CAST(@oldsal AS NVARCHAR(100))
+' to ' +CAST(@newsal AS NVARCHAR(100))
A couple of thoughts:
@oldsal<>@newsal
NULL
NULL
set @auditstring=@auditstring +....
set @auditstring += ...
NULL
NULL
CHAR(size)
VARCHAR(size)
Thanks Lukasz for giving me some tips regarding this.Once i do update in my trigger if problem occurs i will ask again.
– Avish
Jul 1 at 10:06
All good thoughts. This can be done with a set-based operation by joining the
inserted
and deleted
virtual tables on Id
, using CASE
expressions to detect changed values, and using FOR XML
to build the audit string.– Dan Guzman
Jul 1 at 10:09
inserted
deleted
Id
CASE
FOR XML
alter trigger trigger_em_update on emp for update
as begin
Declare @Id int
Declare @oldname varchar(40),@newname varchar(40)
Declare @oldsal int,@newsal int
Declare @oldgen varchar(40),@newgen varchar(40)
Declare @olddeptid int,@newdeptid int
Declare @auditstring nvarchar(max)
--select * from deleted;
select * into #temptable from inserted;
while(Exists(select id from #temptable)) --boolean condition if there are rows are not
Begin
set @auditstring =''
--if there are many rows we still select the first one
select Top 1 @Id =id,@newname=name,@newgen=gender,@newsal=salary,@newdeptid=departmentid
from #temptable;
select Top 1 @Id =id,@oldname=name,@oldgen=gender,@oldsal=salary,@olddeptid=departmentid
from deleted where @Id=id;
set @auditstring=' Employee with id= '+CAST(@Id as varchar(20))+ ' changed '
if(@oldname<>@newname)
set @auditstring+= 'name from '+ @oldname +' to' +@newname
if(@oldsal<>@newsal)
set @auditstring+= 'salary from ' +CAST(@oldsal AS NVARCHAR(100)) + ' to ' +CAST(@newsal AS NVARCHAR(100))
if(@oldgen<>@newgen)
set @auditstring+= 'gender from ' + @oldgen + ' to ' + @newgen
if(@olddeptid<>@newdeptid)
set @auditstring+= 'departmentid from ' + cast(@olddeptid as nvarchar(5))+' to'+cast(@newdeptid as nvarchar(5))
insert into emp_audit values(@auditstring)
delete from #temptable where id=@Id
end
end
when i execute this it gives an error"String or binary data would be truncated" where i did a mistake i don't know please refer the attached screenshot enter image description here
The problem is that one of the columns used with +
is a number, probably salary. But your trigger is way too complicated.
+
SQL is a set-based language. So use the sets when you can:
alter trigger trigger_em_update on emp for update
as
begin
insert into emp_audit (auditstring) -- guessing the name
select ('Employee with id k= ' + CAST(@Id as varchar(20))+ ' changed ' +
(case when @oldname <> @newname
then 'name from '+ @oldname +' to ' + @newname + ' '
else ''
end) +
(case when @oldsal <> @oldsal
then 'salary from '+ convert(varchar(255), @oldsal) +' to ' + concvert(varchar(255), @newsal) + ' '
else ''
end) +
(case when @oldgen <> @newgen
then 'gender from '+ convert(varchar(255), @oldgen) +' to ' + concvert(varchar(255), @newgen) + ' '
else ''
end) +
(case when @olddeptid <> @newdeptid
then 'departmentid from '+ convert(varchar(255), @olddeptid) +' to ' + concvert(varchar(255), @newdeptid) + ' '
else ''
end)
) as auditstring
from inserted i join
deleted d
on i.id = d.id;
end;
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Do any of the columns being logged allow NULLs?
– HABO
Jul 1 at 13:52