拉链表如何实现

什么是拉链表

参考0:https://zhuanlan.zhihu.com/p/578804017

参考1:https://blog.csdn.net/weixin_39948277/article/details/111749235

适用场景:适用于大量数据,少量变更的应用场景

拉链表如何实现

参考0:https://blog.csdn.net/yuxiu_1191610370/article/details/116117008

拉链表实现方式:

1)更新end_date

2)插入变更的记录

3)插入新纪录

链表就是先更新历史数据,再插入变更数据


第一步:创建用于记录用户邮箱变更的拉链表:

1.1 创建拉链表 user_email_history, 假设目标表叫做 user_info (u_id ,u_name , u_sex ,u_birthday, u_address , u_email , u_tel ,u_update )

create table user_email_history
(user_id number(10),                 -- 用户id
user_email varchar2(20),             --用户邮箱
beg_date date,                       --上一次更新时间
end_date date )                     --最后一次更新时间(最后一次更新后,我们将这个时间设置为 5000/12/31,用于查找链表中最后一批更新的数据)

第二步:找到 拉链表中最后一批更新的数据该数据已经发生了变更 , 在拉链表中更新该数据的end_date,使之与目标表时间一致

update user_email_history  as his
 
      set his.end_date  = (select u_update from user_info  where his.id = u_id )
 
where  exist (select  u_update
 
                             from  user_info  as u
 
                     where   his.user_id = u.u_id                                                        -- 用户id  相同
 
                          and  his.user_email != u.u_email                                               --  用户 邮箱不同
 
                          and  his.end_date = to_date ('5000/12/31','yyyy/mm/dd'));                   -- 链表中最后一次更新的数据
 
       commit;

第三步:向拉链表中插入目标表发生变更的数据,最后时间设置为 5000/12/31

insert into user_email_history
     select      u_id,
                 u_email,
                 u_update as beg_date,
                 to_date('5000/12/31', 'yyyy/mm/dd') as end_date
        from user_info u
     where exists (select *
                        from user_email_history as his
                     where   u.u_id = his.user_id
                         and u.u_email != his.user_email 
                         and u.u_update = his.end_date) --因上一步更新了拉链表的需要更新数据的最后时间,这里进行时间等值判断就能找到这部分数据
         and
             --下面这个条件是防止目标表数据变更一次,链表多次更新造成数据重复(这步一定要加,一定要加,一定要加,重要的事情讲三遍)
                 not exists
           (select *
                        from user_email_history as his
                     where u.u_id = his.his.user_id
                         and u.u_email = his.user_email
                         and his.end_date = to_date('5000/12/31', 'yyyy/mm/dd'));        
            commit;

第四步:向链表中插入 目标表中新出现的数据(也就是链表中没有这个记录的新数据)

insert into  user_email_history  as his
    select       u.u_id,
                 u.u_email,
                 u.update as beg_date,
                 to_date('5000/12/31', 'yyyy/mm/dd') as end_date
        from user_info as  u
     where not exists (select * from user_email_history as  where u.u_id = user_id);
commit;

总结一下:链表就是先更新历史数据,再插入变更数据

要注意的就是第三步一定要加过滤条件防止目标表更新一次,链表多次更新,造成数据错误的情况!

posted @ 2023-07-03 09:00  付十一。  阅读(231)  评论(0)    收藏  举报