1 /*拉链表: 也就是一个 记录历史 表,用于记录事物从 最开始的状态 到 当前状态 所有变化的信息 */
2
3 --历史表
4 drop table old_tb_his;
5 drop table new_tb;
6
7
8 --od 我们希望的拉链表记录数据的所有状态,初始化为昨日全量数据
9 create table old_tb_his(
10 id number(10,0),
11 status varchar2(20),
12 start_date varchar2(20),
13 end_date varchar2(20)
14 );
15 insert into old_tb_his values(1,'1', '200712' , '299901');
16 insert into old_tb_his values(2,'2', '200712' , '299901');
17 insert into old_tb_his values(3,'3', '200712' , '299901');
18 insert into old_tb_his values(4,'4', '200712' , '299901');
19 insert into old_tb_his values(5,'5', '200712' , '299901');
20 commit;
21 select * from old_tb_his;
22
23
24 --nd 今日全量数据
25 create table new_tb as select * from old_tb_his where 2 = 1 ;
26 insert into new_tb values(1,'2', '200801' , '299901');
27 insert into new_tb values(2,'2', '200801' , '299901');
28 insert into new_tb values(3,'4', '200801' , '299901');
29 insert into new_tb values(4,'4', '200801' , '299901');
30 insert into new_tb values(5,'6', '200801' , '299901');
31 commit;
32 select * from new_tb;
33
34
35 /*merge into old_tb_his
36 using new_tb
37 on (old_tb_his.id = new_tb.id and old_tb_his.status = new_tb.status )
38 when matched then update set old_tb_his.end_date = new_tb.start_date
39 when not matched then insert values(new_tb.id, new_tb.status, new_tb.start_date,new_tb.end_date);*/
40
41
42 /*
43 用不了 这个函数是匹配就更新 不匹配添加
44 而拉链算法可以看作是 不匹配的更新 不匹配的也添加
45 */
46 /*merge into old_tb_his
47 using new_tb
48 on (old_tb_his.id = new_tb.id and old_tb_his.status = new_tb.status )
49 when not matched then update set old_tb_his.end_date = new_tb.start_date ;
50 when not matched then insert values(new_tb.id, new_tb.status, new_tb.start_date,new_tb.end_date);
51 */
52 --如果函数不能完成拉链算法 只能通过存储过程来完成
53 select * from old_tb_his;
54 select * from new_tb;
55
56
57 drop table old_tb_his_temp;
58 drop table new_tb_temp;
59 --创建临时表old_tb_his_temp
60 create global temporary table old_tb_his_temp
61 (
62 id number(10,0),
63 status varchar2(20),
64 start_date varchar2(20),
65 end_date varchar2(20)
66 )
67 on commit delete rows ;
68
69 --创建临时表new_tb_temp
70 create global temporary table new_tb_temp
71 (
72 id number(10,0),
73 status varchar2(20),
74 start_date varchar2(20),
75 end_date varchar2(20)
76 )
77 on commit delete rows ;
78
79
80 -- w_i = nd - od ( 将w_i表的内容全部插入到历史表中,这些是新增记录 )
81 --今日全量数据减去拉链表数据 等于新增数据 用w_i表示
82 --UNION(无重并集)、UNION ALL(有重并集)、INTERSECT(交集)、MINUS (差集):只显示在第一个集合中存在,在第二个集合中不存在的数据
83 insert into old_tb_his_temp
84 select *
85 from new_tb t
86 where t.id not in (select id--今日全量数据,减去拉链表数据和今日全量数据的交集,等于今日新增数据
87 from (select t1.id, t1.status, t1.end_date
88 from old_tb_his t1
89 intersect
90 select t2.id, t2.status, t2.end_date
91 from new_tb t2));--查询拉链表数据和今日全量数据的交集
92
93 -- w_u = od - nd ( 对历史表进行w_u部份的更新操作,start_date保持不变,而end_date改为当天 )封链
94 insert into new_tb_temp
95 select *
96 from old_tb_his t
97 where t.id not in (select id--拉链表数据,减去拉链表数据和今日全量数据的交集,等于待更新数据
98 from (select t1.id, t1.status, t1.end_date
99 from old_tb_his t1
100 intersect
101 select t2.id, t2.status, t2.end_date
102 from new_tb t2));--查询拉链表数据和今日全量数据的交集
103 --查询两个临时表
104 select * from old_tb_his_temp;
105 select * from new_tb_temp;
106 commit;
107
108 --insert操作把w_i插入到拉链表
109 insert into old_tb_his
110 select * from old_tb_his_temp ;
111 --查询是否成功插入
112 --select * from old_tb_his ;
113
114
115 --多表更新语句一: update 操作按u更新his
116 /*merge into old_tb_his
117 using old_tb_his_temp on (old_tb_his.id = old_tb_his_temp.id and old_tb_his.status <> old_tb_his_temp.status )
118 when matched then update set old_tb_his.end_date = old_tb_his_temp.start_date ;*/
119
120 --多表更新语句二: or: update 操作按u更新his
121 update old_tb_his
122 set old_tb_his.end_date = (select old_tb_his_temp.start_date from old_tb_his_temp where old_tb_his_temp.id = old_tb_his.id)
123 where exists(
124 select 1 from old_tb_his_temp where old_tb_his.id = old_tb_his_temp.id
125 and old_tb_his.status <> old_tb_his_temp.status
126 );
127
128 commit;
129
130
131 select * from old_tb_his
132
133 用户标志 状态 开始时间 结束时间
134 1 1 200712 200801 --change
135 2 2 200712 299901
136 3 3 200712 200801 --change
137 4 4 200712 299901
138 5 5 200712 200801 --change
139 1 2 200801 299901
140 3 4 200801 299901
141 5 6 200801 299901