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