审计字段:即记录数据的创建人、创建时间、修改人、修改时间的字段等,体现在每一张数据库表中。通过审计字段,可以知道数据怎么来的,什么时候同步的,若出现问题也可追溯。

4.1 全量抽取

将目标表的数据全部删除,再将源系统的数据全部插入目标表。此方法保证了数据的质量,但是对于数据量大的表而言,性能太差。

【例】同步EMP表

  1. --创建目标表表结构
  2. CREATE TABLE EMPEMP
  3. ( EMPNO NUMBER(4)
  4. ,ENAME VARCHAR2(10)
  5. ,JOB VARCHAR2(9)
  6. ,MGR NUMBER(4)
  7. ,HIREDATE DATE
  8. ,SAL NUMBER(7,2)
  9. ,COMM NUMBER(7,2)
  10. ,DEPTNO NUMBER(2),
  11. LAST_UPDATE_DATE DATE
  12. )
  13. ALTER TABLE EMPEMP ADD CONSTRAINT PK_EMPNO PRIMARY KEY(EMPNO)
  14. --创建存储过程
  15. CREATE OR REPLACE PROCEDURE SP_EMPA
  16. IS
  17. BEGIN
  18. EXECUTE IMMEDIATE 'TRUNCATE TABLE EMPEMP';
  19. INSERT INTO EMPEMP EE
  20. ( EE.EMPNO,
  21. EE.ENAME,
  22. EE.JOB,
  23. EE.MGR,
  24. EE.HIREDATE,
  25. EE.SAL,
  26. EE.COMM,
  27. EE.DEPTNO,
  28. EE.LAST_UPDATE_DATE )
  29. SELECT E.EMPNO,
  30. E.ENAME,
  31. E.JOB,
  32. E.MGR,
  33. E.HIREDATE,
  34. E.SAL,
  35. E.COMM,
  36. E.DEPTNO,
  37. SYSDATE
  38. FROM EMP E;
  39. COMMIT;
  40. END;
  41. --调用
  42. BEGIN
  43. SP_EMPA;
  44. END;

注意
1.尽量不使用不直观,且有时会使数据插入不对应的字段。
2.表最好别名,给系统减轻识别负担,不易产生分歧。
3.工作中做全量抽取时,通常先判断源表是否有数据,再执行。如果源表没有数据了,同步之后目标表也没有数据了,只能从硬盘里找回数据,成本代价高。

4.2 增量抽取

只需抽取新增的或修改的数据。此方法性能好,但容易遗漏。有时源表更新的字段,在目标表中不存在,则不需要更新。以时间戳取增量,对源表删除的数据无能为力。

① —— MERGE INTO

语法格式:MERGE(不是所有数据库都通用)

  1. MERGE INTO 目标表
  2. USING (增量)
  3. ON (匹配字段)
  4. WHEN MATCHED THEN UPDATE SET --UPDATESET之间不需要加表名
  5. WHEN NOT MATCHED THEN INSERT VALUES
  6. --INSERTVALUES之间不需要加INTO 表名

【例】同步EMP表数据

  1. CREATE OR REPLACE PROCEDURE SP_EMPC(P_START_DATE VARCHAR2,
  2. P_END_DATE VARCHAR2)IS
  3. V_START_DATE DATE:= TO_DATE(P_START_DATE,'YYYY-MM-DD HH24:MI:SS');
  4. V_END_DATE DATE:= TO_DATE(P_END_DATE,'YYYY-MM-DD HH24:MI:SS');
  5. BEGIN
  6. MERGE INTO EMPEMP A
  7. USING(SELECT E.EMPNO,
  8. E.ENAME,
  9. E.JOB,
  10. E.MGR,
  11. E.HIREDATE,
  12. E.SAL,
  13. E.COMM,
  14. E.DEPTNO
  15. FROM EMP E
  16. WHERE E.LAST_UPDATE_DATE >= V_START_DATE
  17. AND E.LAST_UPDATE_DATE < V_END_DATE ) B
  18. ON (A.EMPNO = B.EMPNO)
  19. WHEN MATCHED THEN
  20. UPDATE
  21. SET A.ENAME = B.ENAME,
  22. A.JOB = B.JOB,
  23. A.MGR = B.MGR,
  24. A.HIREDATE = B.HIREDATE,
  25. A.SAL = B.SAL,
  26. A.COMM = B.COMM,
  27. A.DEPTNO = B.DEPTNO,
  28. A.LAST_UPDATE_DATE = SYSDATE
  29. WHEN NOT MATCHED THEN
  30. INSERT
  31. (A.EMPNO,A.ENAME,A.JOB,A.MGR,A.HIREDATE,A.SAL,A.COMM,A.DEPTNO,A.LAST_UPDATE_DATE)
  32. VALUES
  33. (B.EMPNO,B.ENAME,B.JOB,B.MGR,B.HIREDATE,B.SAL,B.COMM,B.DEPTNO,SYSDATE);
  34. COMMIT;
  35. END;
  36. BEGIN
  37. SP_EMPC('2017-04-05 00:00:00','2017-04-06 00:00:00');
  38. END;

② —— 范围之内删除,再插入

先将目标表的记录在增量范围之内的删除,然后再将增量插入

  1. CREATE OR REPLACE PROCEDURE SP_EMPB(P_START_DATE VARCHAR2,
  2. P_END_DATE VARCHAR2)IS
  3. V_START_DATE DATE:= TO_DATE(P_START_DATE,'YYYY-MM-DD HH24:MI:SS');
  4. V_END_DATE DATE:= TO_DATE(P_END_DATE,'YYYY-MM-DD HH24:MI:SS');
  5. BEGIN
  6. DELETE FROM EMPEMP WHERE EMPNO IN(SELECT E.EMPNO
  7. FROM EMP E
  8. WHERE E.LAST_UPDATE_DATE >= V_START_DATE
  9. AND E.LAST_UPDATE_DATE < V_END_DATE);
  10. INSERT INTO EMPEMP A
  11. (A.EMPNO,A.ENAME,A.JOB,A.MGR,A.HIREDATE,A.SAL,A.COMM,A.DEPTNO,A.LAST_UPDATE_DATE)
  12. SELECT E.EMPNO,E.ENAME,E.JOB,E.MGR,E.HIREDATE,E.SAL,E.COMM,E.DEPTNO,SYSDATE
  13. FROM EMP E
  14. WHERE LAST_UPDATE_DATE >= V_START_DATE
  15. AND LAST_UPDATE_DATE < V_END_DATE;
  16. COMMIT;
  17. END;
  18. BEGIN
  19. SP_EMPB('2017-04-05 00:00:00','2017-04-06 00:00:00');
  20. END;

③ —— 游标

使用游标,逐一判断每一条增量记录是需要更新还是插入

  1. CREATE OR REPLACE PROCEDURE SP_EMPD(P_START_DATE VARCHAR2,
  2. P_END_DATE VARCHAR2)IS
  3. V_START_DATE DATE:= TO_DATE(P_START_DATE,'YYYY-MM-DD HH24:MI:SS');
  4. V_END_DATE DATE:= TO_DATE(P_END_DATE,'YYYY-MM-DD HH24:MI:SS');
  5. CURSOR C_UPDATE IS
  6. SELECT E.EMPNO,E.ENAME,E.JOB,E.MGR,E.HIREDATE,E.SAL,E.COMM,E.DEPTNO
  7. FROM EMP E
  8. WHERE E.LAST_UPDATE_DATE >= V_START_DATE
  9. AND E.LAST_UPDATE_DATE < V_END_DATE;
  10. CT NUMBER;
  11. BEGIN
  12. FOR X IN C_UPDATE LOOP
  13. SELECT COUNT(1)INTO CT FROM EMPEMP A WHERE A.EMPNO = X.EMPNO;
  14. IF CT = 1THEN
  15. UPDATE EMPEMP A
  16. SET A.ENAME = X.ENAME,
  17. A.JOB = X.JOB,
  18. A.MGR = X.MGR,
  19. A.HIREDATE = X.HIREDATE,
  20. A.SAL = X.SAL,
  21. A.COMM = X.COMM,
  22. A.DEPTNO = X.DEPTNO,
  23. A.LAST_UPDATE_DATE = SYSDATE
  24. WHERE A.EMPNO = X.EMPNO;
  25. ELSIF CT = 0THEN
  26. INSERT INTO EMPEMP A
  27. (A.EMPNO,A.ENAME,A.JOB,A.MGR,A.HIREDATE,A.SAL,A.COMM,A.DEPTNO,A.LAST_UPDATE_DATE)
  28. VALUES
  29. (X.EMPNO,X.ENAME,X.JOB,X.MGR,X.HIREDATE,X.SAL,X.COMM,X.DEPTNO,X.LAST_UPDATE_DATE,SYSDATE);
  30. END IF;
  31. END LOOP;
  32. COMMIT;
  33. END;
  34. BEGIN
  35. SP_EMPD('2017-04-05 00:00:00','2017-04-06 00:00:00');
  36. END;

—方法四
将增量记录逐一插入目标表,如果违反唯一索引,则更新

CREATEORREPLACEPROCEDURE SP_EMPG(P_START_DATE VARCHAR2,
P_END_DATE VARCHAR2)IS
V_START_DATE DATE:= TO_DATE(P_START_DATE,’YYYY-MM-DD HH24:MI:SS’);
V_END_DATE DATE:= TO_DATE(P_END_DATE,’YYYY-MM-DD HH24:MI:SS’);
CURSOR C_UPDATE IS
SELECT E.EMPNO,
E.ENAME,
E.JOB,
E.MGR,
E.HIREDATE,
E.SAL,
E.COMM,
E.DEPTNO
FROM EMP E
WHERE E.LAST_UPDATE_DATE >= V_START_DATE
AND E.LAST_UPDATE_DATE < V_END_DATE;

BEGIN
FOR X IN C_UPDATE LOOP
BEGIN
INSERTINTO EMPEMP A
(A.EMPNO,
A.ENAME,
A.JOB,
A.MGR,
A.HIREDATE,
A.SAL,
A.COMM,
A.DEPTNO,
A.LAST_UPDATE_DATE)
VALUES
(X.EMPNO,
X.ENAME,
X.JOB,
X.MGR,
X.HIREDATE,
X.SAL,
X.COMM,
X.DEPTNO,
SYSDATE);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
UPDATE EMPEMP A
SET A.ENAME = X.ENAME,
A.JOB = X.JOB,
A.MGR = X.MGR,
A.HIREDATE = X.HIREDATE,
A.SAL = X.SAL,
A.COMM = X.COMM,
A.DEPTNO = X.DEPTNO,
A.LAST_UPDATE_DATE =SYSDATE
WHERE A.EMPNO = X.EMPNO;
END;
ENDLOOP;
END;

BEGIN
SP_EMPG(‘2017-04-05 00:00:00’,’2017-04-06 00:00:00’);
END;

4.3 若数据量大时,MERGE删除比DELETE好。

  1. MERGE INTO EMP E
  2. USING(SELECT * FROM EMP S WHERE S.DEPTNO =10) S
  3. ON(S.EMPNO = E.EMPNO)
  4. WHEN MATCHED THEN
  5. UPDATE
  6. SET E.COMM =1
  7. DELETE WHERE 1=1; --SET随便改,后面接DELETE

Q:如果源表数据删除了怎么办?

源表的数据一般不会被删除,通常表后面会加一个删除标识字段,用来标识这条记录是否失效,即软删除(华为称为打PD),证明这条记录存在过。
如果源表有数据删除了,可以查看源表的 ,看哪些记录被删除了,在目标表相应记录上加上删除标识,但是此方法代价大,成本高。

Q:两张表A、B关联抽数如何抽取?

--方法1
两张表全量关联,A表的时间或B表的时间在时间范围内

--方法2
(A表的增量与B表的全量关联)
UNION ALL
(B表的增量与A表的全量关联)

--方法3
(A的增量主键
union all
B增量主键
group by 主键)
left join A
on 主键
left join B
on 主键