sqlsql-servermergescd2

T-SQL Merge statement type 2 scd


I'm experimenting with the merge statement to ultimately use in to create a SCD type 2 loading procs. The behaviour I'm looking for is:

I've seen uses of the merge statement to simply update a record in the target table to set a deleted date but that's not what I'm looking for. The same code outputs the updated record that is used to insert the new record in case of an update. What I was planning on using was the same mechanism in case of a delete and use coalesce in the output (code below) to return the correct value assuming that if a record was inserted the deleted values would be NULL.

However if I update a record and run my script the deleted collection also contains values (tested this by dumping the deleted.id column to the target table). The id I've update in the source is id 1 and in the target table both deleted_id as well as inserted_id are both 1. I'd expected deleted_id to be null and inserted_id to be 1...

Hereby my script:

    select 
        *
    FROM
        (merge test_rbo as target using test_rbo_source as source on target.id = source.id and target.meta_active = 1
            WHEN not matched by target THEN
                insert (id, name, meta_load_date, meta_load_end_date, meta_deleted, meta_active, action) values (source.id, source.name, getdate(), '9999-12-31 23:59:59', null, 1, 'INSERT')

            WHEN matched and target.name <> source.name THEN
                update set target.meta_load_end_date = GETDATE(), meta_active = 0

            WHEN not matched by source THEN
                update set meta_active = 0

            output         
                coalesce(deleted.id, source.id) as id,
                coalesce(deleted.name, source.name) as name,
                getdate() as meta_load_date,
                '9999-12-31 23:59:59' as meta_load_end_date,
                case when $action = 'DELETE' then getdate() when $action = 'UPDATE' then null end as meta_deleted,
                1 as meta_active,
                $action as action,
                source.id as source_id,
                inserted.id as inserted_id,
                deleted.id as deleted_id
        ) as a
    WHERE  
        action <> 'INSERT';

So basically I'm left wondering whether this is normal behaviour and if the merge statement is even applicable for what I want.

Thanks!


Solution

  • It's not possible to achieve this using the merge statement.