0

I have 2 tables called Customer and ChangeLog. having the following structure

Customer table

Customer Table

ChangeLog Table

Change Log

My Requirement is that

I need an SSIS Package that will read the record from another table with the same structure as CustomerTable and then compare the rows on both tables. If a change in any record is found it updates the records in the customer table as well as put an entry in the ChangeLog saying which column was updated.

So when a change is found in any of the columns I need to do the following

  1. Update the Coresposing record in the Customer Table
  2. Insert a new row into the ChangeLog

There won't be an Insert to the Customer Table. There will be only updates

Is there any single Task in SSIS that I can use to do both the update as well as an insert to these different tables ? or else what is the quickest and efficient way to achieve this in SSIS?

Any help is much appreciated

Tab Alleman
  • 31,483
  • 7
  • 36
  • 52
Jayasurya Satheesh
  • 7,826
  • 3
  • 22
  • 39
  • Does the other table only contain updated rows from your custtable? At least you need to identify a key, and if you look at that key and the rows are different then update. Use a merge statement to do this – SqlKindaGuy Nov 08 '17 at 14:23
  • @plaidDK I can match the records based on CustId. and I know YOu can insert or update the same statement using Merge join. But does that support multiple tables? because Insert and update are done of different tables – Jayasurya Satheesh Nov 08 '17 at 14:25
  • Are your updated values always in another table? Then you can just use a lookup and when it matches the IDs then it goes to an update sql command and an insert task. and when it doesnt match it doesnt do anything – SqlKindaGuy Nov 08 '17 at 14:27
  • Updates are made on the Customer Table. I have another staging table from where I match the records to updates – Jayasurya Satheesh Nov 08 '17 at 14:29
  • Yes but does the changes come from the another table? – SqlKindaGuy Nov 08 '17 at 14:34

2 Answers2

1

No there is no single SSIS task made to do this. I wouldn't use SSIS for this at all. Put the logic in either a stored procedure or trigger. If you have to use SSIS for some reason, then have SSIS call the stored procedure, or UPDATE the table and let the trigger fire.

Tab Alleman
  • 31,483
  • 7
  • 36
  • 52
0

This here is better than a SSIS packages since you can use a trigger to detect your row changes, and even the values.

Try my example you can just C/P into management studio. When you update on Sample_Table you will have changes rows and which column in your table.

  1. So what you can do is. Keep your lookup logic in SSIS (if you want something in SSIS) - Updated the Table based on matches in lookup

  2. When these updates happend your trigger will be fired and update the rows that have changed.

  3. Alternative you can create your lookup in a t-sql script and do an ordinary update when custid=custid instead its just as easy. But thats up to you.

EDITED

     -- -------------------- Setup tables and some initial data --------------------
 CREATE TABLE dbo.Sample_Table (ContactID int, Forename varchar(100), Surname varchar(100), Extn varchar(16), Email varchar(100), Age int );
 INSERT INTO Sample_Table VALUES (1,'Bob','Smith','2295','bs@example.com',24);
 INSERT INTO Sample_Table VALUES (2,'Alice','Brown','2255','ab@example.com',32);
 INSERT INTO Sample_Table VALUES (3,'Reg','Jones','2280','rj@example.com',19);
 INSERT INTO Sample_Table VALUES (4,'Mary','Doe','2216','md@example.com',28);
 INSERT INTO Sample_Table VALUES (5,'Peter','Nash','2214','pn@example.com',25);
 
 CREATE TABLE dbo.Sample_Table_Changes (ContactID int, FieldName sysname, FieldValueWas sql_variant, FieldValueIs sql_variant, modified datetime default (GETDATE()));
 
 GO
 
 -- -------------------- Create trigger --------------------
 CREATE TRIGGER TriggerName ON dbo.Sample_Table FOR DELETE, INSERT, UPDATE AS
 BEGIN
     SET NOCOUNT ON;
     --Unpivot deleted
     WITH deleted_unpvt AS (
         SELECT ContactID, FieldName, FieldValue
         FROM 
            (SELECT ContactID
                 , cast(Forename as sql_variant) Forename
                 , cast(Surname as sql_variant) Surname
                 , cast(Extn as sql_variant) Extn
                 , cast(Email as sql_variant) Email
                 , cast(Age as sql_variant) Age
            FROM deleted) p
         UNPIVOT
            (FieldValue FOR FieldName IN 
               (Forename, Surname, Extn, Email, Age)
         ) AS deleted_unpvt
     ),
     --Unpivot inserted
     inserted_unpvt AS (
         SELECT ContactID, FieldName, FieldValue
         FROM 
            (SELECT ContactID
                 , cast(Forename as sql_variant) Forename
                 , cast(Surname as sql_variant) Surname
                 , cast(Extn as sql_variant) Extn
                 , cast(Email as sql_variant) Email
                 , cast(Age as sql_variant) Age
            FROM inserted) p
         UNPIVOT
            (FieldValue FOR FieldName IN 
               (Forename, Surname, Extn, Email, Age)
         ) AS inserted_unpvt
     )
 
     --Join them together and show what's changed
     INSERT INTO Sample_Table_Changes (ContactID, FieldName, FieldValueWas, FieldValueIs)
     SELECT Coalesce (D.ContactID, I.ContactID) ContactID
         , Coalesce (D.FieldName, I.FieldName) FieldName
         , D.FieldValue as FieldValueWas
         , I.FieldValue AS FieldValueIs 
     FROM 
         deleted_unpvt d
 
             FULL OUTER JOIN 
         inserted_unpvt i
             on      D.ContactID = I.ContactID 
                 AND D.FieldName = I.FieldName
     WHERE
          D.FieldValue <> I.FieldValue --Changes
         OR (D.FieldValue IS NOT NULL AND I.FieldValue IS NULL) -- Deletions
         OR (D.FieldValue IS NULL AND I.FieldValue IS NOT NULL) -- Insertions
 END
 GO
 -- -------------------- Try some changes --------------------
 UPDATE Sample_Table SET age = age+1;
 /*UPDATE Sample_Table SET Extn = '5'+Extn where Extn Like '221_';
 
 DELETE FROM Sample_Table WHERE ContactID = 3;
 
 INSERT INTO Sample_Table VALUES (6,'Stephen','Turner','2299','st@example.com',25);
 
 UPDATE Sample_Table SET ContactID = 7 where ContactID = 4; --this will be shown as a delete and an insert
 -- -------------------- See the results --------------------
 SELECT *, SQL_VARIANT_PROPERTY(FieldValueWas, 'BaseType') FieldBaseType, SQL_VARIANT_PROPERTY(FieldValueWas, 'MaxLength') FieldMaxLength from Sample_Table_Changes;
 
 -- -------------------- Cleanup --------------------
 DROP TABLE dbo.Sample_Table; DROP TABLE dbo.Sample_Table_Changes;*/
 
 select * from dbo.sample_table_changes
Community
  • 1
  • 1
SqlKindaGuy
  • 3,501
  • 2
  • 12
  • 29
  • But i had properbly also made it myself in some kind of stored procedure :) But here is a basic ssis way. – SqlKindaGuy Nov 08 '17 at 14:58
  • So, If only first name for a record is changed and there is no updated on the Lastname, then will it insert only 1 record saying First Name Updated (as expected) or a record saying Record / Row Updated? – Jayasurya Satheesh Nov 09 '17 at 04:52
  • No it will take all. My scenario you have all your values available so it wouldnt matter. – SqlKindaGuy Nov 09 '17 at 07:13
  • But in My scenario, the update may happen to only one column or multiple columns. It may vary for each record – Jayasurya Satheesh Nov 09 '17 at 07:14
  • But Thanks for the Help @plaidDk it was really helpful. To reduce the number of operations that we were currently using – Jayasurya Satheesh Nov 09 '17 at 07:15
  • But why cannot it update the entire rows when you have all your values available anyways? The most important thing is that you get your changes? Anyways, as i write in my first comment, i would make this in stored procedure og some kind og trigger as @Tab Alleman writes – SqlKindaGuy Nov 09 '17 at 07:17
  • I can update the values. But I need to log only those which have any change in values – Jayasurya Satheesh Nov 09 '17 at 07:21
  • Yes then you may need a trigger look here: https://learn.microsoft.com/en-us/sql/t-sql/functions/columns-updated-transact-sql – SqlKindaGuy Nov 09 '17 at 07:23
  • 1
    See also https://stackoverflow.com/questions/1254787/sql-server-update-trigger-get-only-modified-fields/8020461#8020461 – Stephen Turner Jan 21 '20 at 14:50