简体   繁体   中英

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:

  • New Record in source --> insert into target
  • Updated record in source --> EndDate and deactivate target record and add new record in target.
  • Deleted record in source --> Enddate in target record and add new record in target with deleted date set

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!

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM