|
|
|
Valued Member
      
Group: General Forum Members
Last Login: Tuesday, May 21, 2013 4:17 AM
Points: 69,
Visits: 269
|
|
Hi I'm looking at using Merge which I've never used. I've achieved Auditing before with an After trigger that writes the old row to the audit table. I'm only interested in writting to the audit table if the values change so use checksum.
create table tblCustomer (CID int not null primary key, name varchar(10) not null, country varchar(15) not null)
insert into tblCustomer values (1, 'Bob', 'UK'), (2, 'Claire', 'USA'), (3,'Terry','France') create table tblUpdates ( CID int not null, name varchar(10) not null, country varchar(15) not null )
insert into tblUpdates values (1, 'Bob', 'UK'), (2, 'Claire', 'Mexico'), (3,'Terrance','Spain'),(4,'Abdul','Egypt')
select 'UPDATE' as actiontype, getdate() as AuditDate, name, country into #tAudit from tblCustomer where 1=2
insert into #tAudit SELECT Actiontype, AuditDate, name, country FROM ( MERGE tblCustomer AS target USING (SELECT * FROM tblUpdates ) AS source ON (target.cid = source.cid)
WHEN MATCHED THEN UPDATE SET name = source.name, country = source.country WHEN NOT matched THEN INSERT VALUES (CID,Name, Country)
OUTPUT $action as Actiontype, getdate() as AuditDate, CASE WHEN $action = 'INSERT' THEN inserted.name ELSE deleted.name END as name, CASE WHEN $action = 'INSERT' THEN inserted.country ELSE deleted.country END as country, binary_checksum(inserted.name, inserted.country) as chkNew, binary_checksum(deleted.name, deleted.country) as ChkOld) as tChanges WHERE chkNew <> ChkOld
select * from #tAudit
drop table #tAudit drop table tblCustomer drop table tblUpdates
Is there a better way to achive this.
|
|
|
|
|
SSC Eights!
      
Group: General Forum Members
Last Login: 2 days ago @ 1:30 AM
Points: 803,
Visits: 2,124
|
|
You can use the OUTPUT to insert rows into a table rather than the Outer Select, which is rather cumbersome.
this might be better, and you'd need to double check the code works but theres no reason it shouldnt
MERGE tblCustomer AS target USING (SELECT * FROM tblUpdates ) AS source ON (target.cid = source.cid)
WHEN MATCHED AND (target.name!=source.name or target.country!=source.country) THEN UPDATE SET name = source.name, country = source.country WHEN NOT matched THEN INSERT VALUES (CID,Name, Country)
OUTPUT $action , getdate() , CASE WHEN $action = 'INSERT' THEN inserted.name ELSE deleted.name END as name , CASE WHEN $action = 'INSERT' THEN inserted.country ELSE deleted.country END as country , binary_checksum(inserted.name, inserted.country) as chkNew ,binary_checksum(deleted.name, deleted.country) as ChkOld) as tChanges INTO #tAudit WHERE chkNew <> ChkOld
Edit I've just seen that you dont have a clause to update only the rows that have changed, so I've added it to the code this will then only update changed rows and insert new rows.
_________________________________________________________________________ SSC Guide to Posting and Best Practices
|
|
|
|
|
SSCertifiable
       
Group: General Forum Members
Last Login: Yesterday @ 9:27 AM
Points: 5,618,
Visits: 10,990
|
|
|
|
|
|
Valued Member
      
Group: General Forum Members
Last Login: Tuesday, May 21, 2013 4:17 AM
Points: 69,
Visits: 269
|
|
Thank you. Your example is easier to read.
BTW I was restricting to only chnage rows by comparing the checksum values.
I didn't know you could add additional filters after is matched i.e. target.name != source.name
|
|
|
|
|
SSC Eights!
      
Group: General Forum Members
Last Login: 2 days ago @ 1:30 AM
Points: 803,
Visits: 2,124
|
|
terry999 (10/2/2012) Thank you. Your example is easier to read.
BTW I was restricting to only chnage rows by comparing the checksum values.
I didn't know you could add additional filters after is matched i.e. target.name != source.name
Sorry theres a coding error I believe it should read
MERGE tblCustomer AS target USING (SELECT * FROM tblUpdates ) AS source ON (target.cid = source.cid)
WHEN MATCHED AND (target.name!=source.name or target.country!=source.country) THEN UPDATE SET name = source.name, country = source.country WHEN NOT matched THEN INSERT VALUES (CID,Name, Country)
OUTPUT $action , getdate() , CASE WHEN $action = 'INSERT' THEN inserted.name ELSE deleted.name END , CASE WHEN $action = 'INSERT' THEN inserted.country ELSE deleted.country END , binary_checksum(inserted.name, inserted.country) ,binary_checksum(deleted.name, deleted.country) INTO #tAudit
_________________________________________________________________________ SSC Guide to Posting and Best Practices
|
|
|
|
|
SSCommitted
      
Group: General Forum Members
Last Login: Tuesday, January 15, 2013 11:11 AM
Points: 1,945,
Visits: 2,782
|
|
Look at audit tools that will capture all the data and not be illegal.
Books in Celko Series for Morgan-Kaufmann Publishing Analytics and OLAP in SQL Data and Databases: Concepts in Practice Data, Measurements and Standards in SQL SQL for Smarties SQL Programming Style SQL Puzzles and Answers Thinking in Sets Trees and Hierarchies in SQL
|
|
|
|
|
Valued Member
      
Group: General Forum Members
Last Login: Tuesday, May 21, 2013 4:17 AM
Points: 69,
Visits: 269
|
|
Thanks Jason
I had made that change.
From now on I will use MERGE to replace Triggers for audit - all in one place.
|
|
|
|
|
Valued Member
      
Group: General Forum Members
Last Login: Tuesday, May 21, 2013 4:17 AM
Points: 69,
Visits: 269
|
|
|
|
|
|
Hall of Fame
       
Group: General Forum Members
Last Login: Today @ 12:01 PM
Points: 3,582,
Visits: 5,130
|
|
terry999 (10/2/2012) Thanks Jason
I had made that change.
From now on I will use MERGE to replace Triggers for audit - all in one place.
Note that this places the onus on the developer to code the audit stuff for EVERY SINGLE DML OPERATION ON EACH TABLE. A trigger can be written once and will capture ALL DML operations, regardless of provenance. Even if your devs are rigorous, what about that quick "oopsie" data cleanup operation you need to do because someone screwed something up. Will you ALWAYS remember to do the MERGE, even for ad hoc DML?
Best,
Kevin G. Boles SQL Server Consultant SQL MVP 2007-2012 TheSQLGuru at GMail
|
|
|
|
|
Valued Member
      
Group: General Forum Members
Last Login: Tuesday, May 21, 2013 4:17 AM
Points: 69,
Visits: 269
|
|
| Good point, I'd forgotten that
|
|
|
|