-------------------------数据更新------------
--数据更新分为两种:
全量更新和增量更新。
--全量更新:删除整张表的数据,然后再把最新的全部数据插入到表中。
--适用范围:维度表(数据量少),数据量比较少的事实表或者宽表。
--增量更新:不删除或者删除部分表中数据,只把最新产生的数据插入到表中,历史数据不动。
--适用范围:数据量一定范围内增量比较大的表。一般是事实表或者宽表。
--------------------------------增量更新------------------------
--增量更新一共有4种方法。
---方法一:切片增量更新:按照时间将数据切成片,每次更新时只更新某一片或某几片数据。
----更新方法:先把目标时间范围内的数据删除(目标范围内存在数据就删除,不存在就不删),然后再把目标范围内的最新数据插入进去。
CREATE OR REPLACE PROCEDURE SP_DW_ROOM_DETAIL2(P_START_TIME VARCHAR2,P_END_TIME VARCHAR2) AS
V_START_TIME DATE := TO_DATE(P_START_TIME,'YYYY-MM-DD');
V_END_TIME DATE := TO_DATE(P_END_TIME,'YYYY-MM-DD');
BEGIN
DELETE FROM DW_ROOM_DETAIL WHERE DATEKEY BETWEEN V_START_TIME AND V_END_TIME;
INSERT INTO dw_room_detail
(datekey, date_year, date_month, chainid, status_rmng, status_rm, amountrmng, roomamount, revenue)
SELECT D.DATEKEY,
D.YEARSS AS date_year,
D.MONTHSS AS date_month,
A.CHAINID,
SUM(A.STATUSRMNG) AS status_rmng,
SUM(A.STATUSRMNG+A.ROOMDAY+A.ROOMHALFDAY+A.ROOMHOURDAY) AS status_rm,
SUM(NVL(B.AMOUNTRMNG,0)) AS AmountRmNg,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)) AS RoomAmount,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)+NVL(B.AMOUNTOTHER,0)) AS Revenue
FROM ODS.ODS_T_DATE D
JOIN ODS.ODS_roomcount_detail A
ON D.DATEKEY=TO_DATE(A.DATEKEY,'YYYYMMDD')
JOIN ODS.ODS_ROOMAMOUNT_DETAIL B
ON A.DATEKEY=B.DATEKEY
AND A.CHAINID=B.CHAINID
AND A.ROOMTYPEID=B.ROOMTYPEID
WHERE D.DATEKEY BETWEEN V_START_TIME AND V_END_TIME
GROUP BY D.DATEKEY,
D.YEARSS,
D.MONTHSS,
A.CHAINID;
COMMIT;
END;
-----------------------------
--方法二:使用merge..into..更新(只能在Oracle中使用)
--语法:
MERGE INTO 目标表 --目标表指的是要更新数据的表
USING (增量) --增量指的是SELECT查询语句
ON (匹配字段) --匹配字段指的是能匹配到一条数据的一个字段或者多个字段(一次只能匹配一条数据)
WHEN MATCHED THEN UPDATE SET --UPDATE 和 SET 之间不需要加表名,匹配字段不需要更新。
WHEN NOT MATCHED THEN INSERT VALUES --INSERT 和 VALUES 之间不需要加 INTO 表名
--注释:需要插入数据,说明匹配字段匹配不到,此时需要插入整条数据,一个字段都不能少。
CREATE OR REPLACE PROCEDURE SP_DW_ROOM_DETAIL3(P_START_TIME VARCHAR2,P_END_TIME VARCHAR2) AS
V_START_TIME DATE := TO_DATE(P_START_TIME,'YYYY-MM-DD');
V_END_TIME DATE := TO_DATE(P_END_TIME,'YYYY-MM-DD');
BEGIN
MERGE INTO DW_ROOM_DETAIL M
USING (SELECT D.DATEKEY,
D.YEARSS AS date_year,
D.MONTHSS AS date_month,
A.CHAINID,
SUM(A.STATUSRMNG) AS status_rmng,
SUM(A.STATUSRMNG+A.ROOMDAY+A.ROOMHALFDAY+A.ROOMHOURDAY) AS status_rm,
SUM(NVL(B.AMOUNTRMNG,0)) AS AmountRmNg,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)) AS RoomAmount,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)+NVL(B.AMOUNTOTHER,0)) AS Revenue
FROM ODS.ODS_T_DATE D
JOIN ODS.ODS_roomcount_detail A
ON D.DATEKEY=TO_DATE(A.DATEKEY,'YYYYMMDD')
JOIN ODS.ODS_ROOMAMOUNT_DETAIL B
ON A.DATEKEY=B.DATEKEY
AND A.CHAINID=B.CHAINID
AND A.ROOMTYPEID=B.ROOMTYPEID
WHERE D.DATEKEY BETWEEN V_START_TIME AND V_END_TIME
GROUP BY D.DATEKEY,
D.YEARSS,
D.MONTHSS,
A.CHAINID) N
ON (M.DATEKEY=N.DATEKEY AND M.CHAINID=N.CHAINID)
WHEN MATCHED THEN UPDATE SET
M.date_year = N.date_year,
M.date_month = N.date_month,
M.status_rmng = N.status_rmng,
M.status_rm = N.status_rm,
M.amountrmng = N.amountrmng,
M.roomamount = N.roomamount,
M.revenue = N.revenue
WHEN NOT MATCHED THEN INSERT
(M.DATEKEY,
M.DATE_YEAR,
M.DATE_MONTH,
M.CHAINID,
M.STATUS_RMNG,
M.STATUS_RM,
M.AMOUNTRMNG,
M.ROOMAMOUNT,
M.REVENUE)
VALUES
(N.DATEKEY,
N.DATE_YEAR,
N.DATE_MONTH,
N.CHAINID,
N.STATUS_RMNG,
N.STATUS_RM,
N.AMOUNTRMNG,
N.ROOMAMOUNT,
N.REVENUE);
COMMIT;
END;
-------------------------
--方法三:使用游标增量更新
--操作方法:先把增量放入游标中,然后在逻辑体中一条一条数据的去判断,如果能够匹配到这条数据,就更新为最新的数据,
--如果匹配不到,就把这条数据插入到目标表中。
CREATE OR REPLACE PROCEDURE SP_DW_ROOM_DETAIL4(P_START_TIME VARCHAR2,P_END_TIME VARCHAR2) AS
V_START_TIME DATE := TO_DATE(P_START_TIME,'YYYY-MM-DD');
V_END_TIME DATE := TO_DATE(P_END_TIME,'YYYY-MM-DD');
CURSOR C_DW_ROOM_DETAIL IS
SELECT D.DATEKEY,
D.YEARSS AS date_year,
D.MONTHSS AS date_month,
A.CHAINID,
SUM(A.STATUSRMNG) AS status_rmng,
SUM(A.STATUSRMNG+A.ROOMDAY+A.ROOMHALFDAY+A.ROOMHOURDAY) AS status_rm,
SUM(NVL(B.AMOUNTRMNG,0)) AS AmountRmNg,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)) AS RoomAmount,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)+NVL(B.AMOUNTOTHER,0)) AS Revenue
FROM ODS.ODS_T_DATE D
JOIN ODS.ODS_roomcount_detail A
ON D.DATEKEY=TO_DATE(A.DATEKEY,'YYYYMMDD')
JOIN ODS.ODS_ROOMAMOUNT_DETAIL B
ON A.DATEKEY=B.DATEKEY
AND A.CHAINID=B.CHAINID
AND A.ROOMTYPEID=B.ROOMTYPEID
WHERE D.DATEKEY BETWEEN V_START_TIME AND V_END_TIME
GROUP BY D.DATEKEY,
D.YEARSS,
D.MONTHSS,
A.CHAINID;
V_CNT NUMBER;
BEGIN
FOR X IN C_DW_ROOM_DETAIL LOOP
SELECT COUNT(*)
INTO V_CNT
FROM DW_ROOM_DETAIL B
WHERE B.DATEKEY = X.DATEKEY
AND B.CHAINID=X.CHAINID;
IF V_CNT = 1 THEN
UPDATE DW_ROOM_DETAIL A SET
A.date_year = X.date_year,
A.date_month = X.date_month,
A.status_rmng = X.status_rmng,
A.status_rm = X.status_rm,
A.amountrmng = X.amountrmng,
A.roomamount = X.roomamount,
A.revenue = X.revenue
WHERE A.DATEKEY = X.DATEKEY
AND A.CHAINID=X.CHAINID;
ELSE INSERT INTO dw_room_detail
(datekey, date_year, date_month, chainid, status_rmng, status_rm, amountrmng, roomamount, revenue)
VALUES
(X.DATEKEY,
X.DATE_YEAR,
X.DATE_MONTH,
X.CHAINID,
X.STATUS_RMNG,
X.STATUS_RM,
X.AMOUNTRMNG,
X.ROOMAMOUNT,
X.REVENUE);
END IF;
END LOOP;
COMMIT;
END;
-----------------------------
--方法四:利用异常处理的逻辑增量更新
--操作方法:先把增量数据放入游标中,在逻辑体中直接把增量数据一条一条的插入到目标表中,
---如果违反主键约束,则进入异常处理,改为更新这条数据。
CREATE OR REPLACE PROCEDURE SP_DW_ROOM_DETAIL5(P_START_TIME VARCHAR2,P_END_TIME VARCHAR2) AS
V_START_TIME DATE := TO_DATE(P_START_TIME,'YYYY-MM-DD');
V_END_TIME DATE := TO_DATE(P_END_TIME,'YYYY-MM-DD');
CURSOR C_DW_ROOM_DETAIL IS
SELECT D.DATEKEY,
D.YEARSS AS date_year,
D.MONTHSS AS date_month,
A.CHAINID,
SUM(A.STATUSRMNG) AS status_rmng,
SUM(A.STATUSRMNG+A.ROOMDAY+A.ROOMHALFDAY+A.ROOMHOURDAY) AS status_rm,
SUM(NVL(B.AMOUNTRMNG,0)) AS AmountRmNg,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)) AS RoomAmount,
SUM(NVL(B.AMOUNTRMNG,0)+NVL(B.AMOUNTRMALLDAY,0)+NVL(B.AMOUNTRMOTHER,0)+NVL(B.AMOUNTRMDISCOUNT,0)+NVL(B.AMOUNTOTHER,0)) AS Revenue
FROM ODS.ODS_T_DATE D
JOIN ODS.ODS_roomcount_detail A
ON D.DATEKEY=TO_DATE(A.DATEKEY,'YYYYMMDD')
JOIN ODS.ODS_ROOMAMOUNT_DETAIL B
ON A.DATEKEY=B.DATEKEY
AND A.CHAINID=B.CHAINID
AND A.ROOMTYPEID=B.ROOMTYPEID
WHERE D.DATEKEY BETWEEN V_START_TIME AND V_END_TIME
GROUP BY D.DATEKEY,
D.YEARSS,
D.MONTHSS,
A.CHAINID;
BEGIN
FOR X IN C_DW_ROOM_DETAIL LOOP
BEGIN
INSERT INTO dw_room_detail
(datekey, date_year, date_month, chainid, status_rmng, status_rm, amountrmng, roomamount, revenue)
VALUES
(X.datekey, X.date_year, X.date_month, X.chainid, X.status_rmng, X.status_rm, X.amountrmng, X.roomamount, X.revenue);
EXCEPTION --一旦出现异常
WHEN DUP_VAL_ON_INDEX THEN
UPDATE dw_room_detail A SET
A.date_year = X.date_year,
A.date_month = X.date_month,
A.status_rmng = X.status_rmng,
A.status_rm = X.status_rm,
A.amountrmng = X.amountrmng,
A.roomamount = X.roomamount,
A.revenue = X.revenue
WHERE A.DATEKEY=X.DATEKEY
AND A.CHAINID=X.CHAINID;
END;
END LOOP;
COMMIT;
END;