增量同步相关

----------------------增量同步

逻辑:用源表的数据更新目标表,如果目标表中存在该数据则更新,如果不存在则插入
实现逻辑:首先,判断目标表中是否存在源表的数据(比较字段)
          如果有,则用源表中的数据更新目标表中的对应的该数据
          如果没有,则直接将源表中的数据插入到目标表


--有两种方式:
1、游标 (sp+游标的方式)
2、MERGE INTO (不适用于所有的数据库,oracle数据库独有)


---------游标的方式

--比如:将emp表中的数据通过增量同步的方式抽取到 EMP_TAG
--第一步:建表(表已经存在,就不需要建了)

--第二步:同步数据的存储过程(游标)
CREATE OR REPLACE PROCEDURE SP_EMP_TAG_CURSOR 
IS     
    --定义一个游标指向数据来源的结果集
  CURSOR C_EMP_TAG
  IS
  SELECT  E.empno, 
          E.ename, 
          E.job, 
          E.mgr, 
          E.hiredate, 
          E.sal, 
          E.comm, 
          E.deptno,
          SYSDATE AS CHECK_DATE
  FROM EMP E;     ---注意:不要用 *,而是把所有的列名写出来
  
  CT NUMBER;
BEGIN
  FOR X IN C_EMP_TAG LOOP
    --判断目标表中是否存在源表的数据
    SELECT COUNT(*)
    INTO CT
    FROM EMP_TAG T 
    WHERE T.EMPNO = X.EMPNO; --用来判断的值肯定是可以拿到一条具体的信息
    
    --目标表中没有源表中的数据,插入数据
    IF CT =  0 THEN
      INSERT INTO EMP_TAG(EMPNO,
                          ENAME,
                          JOB,
                          MGR,
                          HIREDATE,
                          SAL,
                          COMM,
                          DEPTNO,
                          CHECK_DATE)
             /*     SELECT  E.empno, 
                          E.ename, 
                          E.job, 
                          E.mgr, 
                          E.hiredate, 
                          E.sal, 
                          E.comm, 
                          E.deptno,
                          SYSDATE
                    FROM EMP E
                    WHERE E.EMPNO = X.EMPNO;*/
                   VALUES(X.EMPNO,
                          X.ENAME,
                          X.JOB,
                          X.MGR,
                          X.HIREDATE,
                          X.SAL,
                          X.COMM,
                          X.DEPTNO,
                          X.CHECK_DATE);
      COMMIT;
     ELSIF CT = 1 THEN 
          UPDATE EMP_TAG T SET  /*T.EMPNO         = X.EMPNO,*/  ---比较字段不更新
                              T.ENAME         = X.ENAME,
                              T.JOB           = X.JOB,
                              T.MGR           = X.MGR,
                              T.HIREDATE      = X.HIREDATE,
                              T.SAL           = X.SAL,
                              T.COMM          = X.COMM,
                              T.DEPTNO        = X.DEPTNO,
                              T.CHECK_DATE    = X.CHECK_DATE
                           WHERE T.EMPNO      = X.EMPNO;
        COMMIT;
    END IF;
  END LOOP;
END;

---每写完一句dml语句时,都带一句tcl(commit/rollback),提高性能的一个小小的点

--测试一下
SELECT * FROM EMP_TAG FOR UPDATE;

BEGIN
  SP_EMP_TAG_CURSOR;
END;


/*小练习一把:创建一个目标表EMP_M(EMP_NO,E_NAME,JOB,HIRE_DATE,DEPT_NO,D_NAME),
  将源表(EMP+DEPT)中的数据增量同步过来
*/
CREATE OR REPLACE PROCEDURE SP_EMP_M_CURSOR
IS
    CURSOR C_EMP_M
  IS
  SELECT  E.empno,
          E.ename,
          E.job,
          E.mgr,
          E.hiredate,
          D.deptno,
          D.DNAME,
          SYSDATE AS CHECK_DATE
  FROM EMP E JOIN DEPT D
  ON E.DEPTNO = D.DEPTNO;
  CT NUMBER;
BEGIN
  FOR X IN C_EMP_M LOOP
    SELECT COUNT(*)
    INTO CT
    FROM EMP_M T
    WHERE T.EMP_NO = X.EMPNO;

    IF CT = 0 THEN
      INSERT INTO EMP_M(EMP_NO,
                        E_NAME,
                        JOB,
                        HIRE_DATE,
                        DEPT_NO,
                        D_NAME,
                        LAST_UPDATE_DATE)
                VALUES (X.EMPNO,
                        X.ENAME,
                        X.JOB,
                        X.HIREDATE,
                        X.DEPTNO,
                        X.DNAME,
                        X.CHECK_DATE);
      COMMIT;

    ELSIF CT = 1 THEN
      UPDATE EMP_M M SET  M.E_NAME            = X.ENAME,
                          M.JOB               = X.JOB,
                          M.HIRE_DATE         = X.HIREDATE,
                          M.DEPT_NO           = X.DEPTNO,
                          M.D_NAME            = X.DNAME,
                          M.LAST_UPDATE_DATE  = X.CHECK_DATE
                  WHERE   M.EMP_NO             = X.EMPNO;
      COMMIT;
    END IF;
  END LOOP;
END;

--测试一下
SELECT * FROM EMP_M FOR UPDATE;

BEGIN
  SP_EMP_M_CURSOR;
END;

---------MERGE INTO的方式
--语法结构
MERGE INTO 目标表
USING (增量)     ---就是数据源的一个结果集,一般就取个别名
ON (匹配字段)    ---目标表中的某个字段 = 上面的这个结果集种的某个字段
WHEN MATCHED THEN UPDATE SET          --UPDATE和SET之间不需要加表名
WHEN NOT MATCHED THEN INSERT VALUES;  --NSERT和VALUES之间不需要加 INTO 表名(目标表的名),但是可以加 列名(目标表中的列)
COMMIT;
  
--比如:将emp表中的数据通过增量同步的方式抽取到 EMP_TAG
--第一步:建表(表已经存在,就不需要建了)

--第二步:同步数据的存储过程(MERGE INTO)
CREATE OR REPLACE PROCEDURE SP_EMP_TAG_MERGE
IS
BEGIN
  MERGE INTO EMP_TAG T
  USING (SELECT empno,
                ename,
                job,
                mgr,
                hiredate,
                sal,
                comm,
                deptno,
                SYSDATE AS check_date FROM EMP) F
  ON (T.EMPNO = F.EMPNO)
  ---在目标表中可以匹配到源表中的数据
  WHEN MATCHED THEN UPDATE SET /* T.EMPNO         = F.EMPNO*/ ---匹配字段不更新
                                T.ENAME         = F.ENAME,
                                T.JOB           = F.JOB,
                                T.MGR           = F.MGR,
                                T.HIREDATE      = F.HIREDATE,
                                T.SAL           = F.SAL,
                                T.COMM          = F.COMM,
                                T.DEPTNO        = F.DEPTNO,
                                T.CHECK_DATE    = F.CHECK_DATE
                                
  ---在目标表中匹配不到源表中的数据
    WHEN NOT MATCHED THEN INSERT VALUES ( F.EMPNO,
                                        F.ENAME,
                                        F.JOB,
                                        F.MGR,
                                        F.HIREDATE,
                                        F.SAL,
                                        F.COMM,
                                        F.DEPTNO,
                                        F.CHECK_DATE);
   COMMIT; ---不要忘
END;

--测试一下
SELECT * FROM EMP_TAG FOR UPDATE;

BEGIN
  SP_EMP_TAG_MERGE;
END;


/*小练习一把:创建一个目标表EMP_M(EMP_NO,E_NAME,JOB,HIRE_DATE,DEPT_NO,D_NAME),
  将源表(EMP+DEPT)中的数据增量同步过来
*/
CREATE OR REPLACE PROCEDURE SP_EMP_M_MERGE
IS
BEGIN
  MERGE INTO EMP_M M
  USING(SELECT  E.empno,
                E.ename,
                E.job,
                E.mgr,
                E.hiredate,
                D.deptno,
                D.DNAME,
                SYSDATE AS CHECK_DATE
                FROM EMP E JOIN DEPT D ON E.DEPTNO = D.DEPTNO) F
  ON (M.EMP_NO = F.EMPNO)
  WHEN MATCHED THEN UPDATE SET  M.E_NAME            = F.ENAME,
                                M.JOB               = F.JOB,
                                M.HIRE_DATE         = F.HIREDATE,
                                M.DEPT_NO           = F.DEPTNO,
                                M.D_NAME            = F.DNAME,
                                M.LAST_UPDATE_DATE  = F.CHECK_DATE
                                
   WHEN NOT MATCHED THEN INSERT (M.EMP_NO,
                                 M.E_NAME,                                      
                                 M.JOB ,            
                                 M.HIRE_DATE  ,     
                                 M.DEPT_NO ,        
                                 M.D_NAME   ,       
                                 M.LAST_UPDATE_DATE)
                         VALUES (F.EMPNO,
                                 F.ENAME,
                                 F.JOB,
                                 F.HIREDATE,
                                 F.DEPTNO,
                                 F.DNAME,
                                 F.CHECK_DATE);
     COMMIT;                                
END;   
                               
--测试一下
SELECT * FROM EMP_M FOR UPDATE;

BEGIN
  SP_EMP_M_MERGE;
END;

-----------总结一下:
全量同步 跟 增量同步的优劣性:
1、全量同步在数据的正确性方面 要比 增量同步 要好
    增量 对 源表中删除的数据 以及  目标表中修改过比较字段/重复的数据 无能为力
  
2、全量同步在性能方面 要比 增量同步 要差
    取决于数据量的大小(一般百万级以下的可以用全量,百万级以上的基本上都是增量了)
  
3、全量同步之前需要注意:源表中是否有数据
  (如果没有源表中没有数据的话,同步之后,目标表中的数据就会被清空,找回的成本就比较大)
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值