CREATE TABLE S01_LSB (
ACTNO NUMBER(4) PRIMARY KEY
,OPNAME VARCHAR(10)
,PASSWD VARCHAR(6)
,CASH NUMBER(10,2)
,OPDATE DATE
,OPADDR VARCHAR(30)
)
;
-- Add comments to the table
comment on table S01_LSB
is '业务帐号流水表';
-- Add comments to the columns
comment on column S01_LSB.ACTNO
is '帐号';
comment on column S01_LSB.OPNAME
is '开户人姓名';
comment on column S01_LSB.PASSWD
is '密码';
comment on column S01_LSB.CASH
is '余额';
comment on column S01_LSB.OPDATE
is '开户日期';
comment on COLUMN S01_LSB.OPADDR
is '开户地址';
CREATE TABLE S01_LLB (
ACTNO NUMBER(4) PRIMARY KEY
,OPNAME VARCHAR(10)
,PASSWD VARCHAR(6)
,CASH NUMBER(10,2)
,OPDATE DATE
,OPADDR VARCHAR(30)
,ETL_START_DATE DATE
,ETL_END_DATE DATE
)
;
-- Add comments to the table
comment on table S01_LSB
is '业务帐号流水表';
-- Add comments to the columns
comment on column S01_LSB.ACTNO
is '帐号';
comment on column S01_LSB.OPNAME
is '开户人姓名';
comment on column S01_LSB.PASSWD
is '密码';
comment on column S01_LSB.CASH
is '余额';
comment on column S01_LSB.OPDATE
is '开户日期';
comment on COLUMN S01_LSB.OPADDR
is '开户地址';
略
–此脚本算法是从技术缓冲层(SDB)向近源模型层(ODB)加载状态类有删除表的带删除拉链算法(FULL JOIN方式)
DROP TABLE scott.T_S01_LLB;
commit;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
CREATE TABLE scott.T_S01_LLB AS
SELECT T.*,' 'as DEL_IND FROM scott.S01_LLB T
WHERE 1=2;
commit;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
DELETE FROM SCOTT.S01_LLB WHERE ETL_START_DATE >= SYSDATE;
commit;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
UPDATE scott.S01_LLB SET ETL_END_DATE = DATE '3000-12-31'
WHERE ETL_END_DATE >=SYSDATE;
commit;
删除旧临时表,同时删除ETL开始日期大于等于今天,修改ETL结束日期为今天的记录。
这一步的目的是为了支持重跑,当脚本报错或者需要修改时,删除今天拉链加载进模型层的数据,可以重新执行拉链脚本加载数据。
ETL_START_DATE与ETL_END_DATE可以按天结算(MM-DD-YYYY),这里偷懒直接读取系统时间,每次执行脚本都会根据系统时间判断新增数据;
INSERT /*+ append */ INTO scott.T_S01_LLB (
ACTNO
,OPNAME
,PASSWD
,CASH
,OPDATE
,OPADDR
,ETL_START_DATE
,ETL_END_DATE
,DEL_IND)
SELECT
N.ACTNO
, N.OPNAME
, N.PASSWD
, N.CASH
, N.OPDATE
, N.OPADDR
, SYSDATE
, DATE '3000-12-31'
, CASE WHEN ( N.ACTNO IS NULL ) THEN 'D' ELSE 'N' END
FROM
(SELECT
ACTNO
,OPNAME
,PASSWD
,CASH
,OPDATE
,OPADDR
FROM SCOTT.S01_LSB ) N
FULL JOIN
(SELECT
ACTNO
,OPNAME
,PASSWD
,CASH
,OPDATE
,OPADDR
FROM SCOTT.S01_LLB
WHERE ETL_END_DATE = DATE '3000-12-31' ) T
ON NVL(N.ACTNO,0)=NVL(T.ACTNO,0)
WHERE
( T.ACTNO IS NULL ) OR ( N.ACTNO IS NULL ) OR (
NVL(N.OPNAME,0) <> NVL(T.OPNAME,0)
OR NVL(N.PASSWD,0) <> NVL(T.PASSWD,0)
OR NVL(N.CASH,0) <> NVL(T.CASH,0)
OR NVL(TO_CHAR(N.OPDATE),0) <> NVL(TO_CHAR(T.OPDATE),0)
OR NVL(N.OPADDR,0) <> NVL(T.OPADDR,0)
);
commit;
将T_S01_LLB中插入数据,内容为:S01_LSB与S01_LLB的全链接,连接条件是帐号相同,筛选出所有帐号相同,其他内容不同的记录、流水表有而拉链表没有的记录(标记DEL_IND为“N”,代表新增记录)、拉链表有而流水表没有的记录(标记DEL_IND为“D”,代表不需要从流水表拉链进入贴源层的记录)
merge into (SELECT * FROM SCOTT.S01_LLB WHERE ETL_END_DATE= DATE '3000-12-31') T
using SCOTT.T_S01_LLB N on ( NVL(N.ACTNO,0)=NVL(T.ACTNO,0) )
when MATCHED then
update set ETL_END_DATE=SYSDATE
;
commit;
用T_S01_LLB与S01_LLB进行merge更新,将上一部插入临时表所有新变更记录、与拉链表帐号相同的旧记录merge into比对,对匹配到的正式拉链表中的记录ETL_END_DATE时间从无穷大闭链为当前时间。
INSERT INTO SCOTT.S01_LLB
SELECT
ACTNO
,OPNAME
,PASSWD
,CASH
,OPDATE
,OPADDR
,ETL_START_DATE
,ETL_END_DATE
FROM SCOTT.T_S01_LLB
WHERE DEL_IND='N';
COMMIT;
这里DEL_IND为“N”的记录包括两部分:
①:拉链表中无,流水表中有的记录
②:拉链表与流水表匹配到且满足where条件内容变更的记录
拉链到此已完成从流水表更新到了拉链表。