zoukankan      html  css  js  c++  java
  • Oracle2MySQL数据校验

    0. 示例表数据

    root@localhost[demo]> select * from demo.tcustmer;
    +-----------+--------------------+-------------+-------+
    | CUST_CODE | NAME               | CITY        | STATE |
    +-----------+--------------------+-------------+-------+
    | ANN       | ANN'S BOATS        | NEW YORK    | NY    |
    | BILL      | BILL'S USED CARS   | DENVER      | CO    |
    | DAVE      | DAVE'S PLANES INC. | TALLAHASSEE | FL    |
    | JANE      | ROCKY FLYER INC.   | DENVER      | CO    |
    | WILL      | BG SOFTWARE CO.    | SEATTLE     | WA    |
    +-----------+--------------------+-------------+-------+
    

    1. MySQL端数据校验

    1.1 MySQL列转行

    -- 设置字段拼接最大长度,防止字段过多显示不全
    SET @@GLOBAL.GROUP_CONCAT_MAX_LEN=10000,@@GROUP_CONCAT_MAX_LEN=10000;
    SELECT @@GLOBAL.GROUP_CONCAT_MAX_LEN,@@GROUP_CONCAT_MAX_LEN;
    
    -- 查询COLUMNS表元数据做字段拼接
    SELECT TABLE_NAME,
           CONCAT(GROUP_CONCAT(COLUMN_NAME ORDER BY ORDINAL_POSITION SEPARATOR ',')) AS ALL_COLUMNS
      FROM INFORMATION_SCHEMA.COLUMNS
     WHERE TABLE_SCHEMA = 'demo'
       AND TABLE_NAME = 'tcustmer'
     GROUP BY TABLE_NAME;
    
    -- 输出结果如下
    +------------+---------------------------+
    | TABLE_NAME | ALL_COLUMNS               |
    +------------+---------------------------+
    | tcustmer   | CUST_CODE,NAME,CITY,STATE |
    +------------+---------------------------+
    

    1.2 MySQL数据校验

    -- 使用MD5对拼接的字段做校验,生成16进制校验码
    SELECT upper(MD5(CONCAT_WS('',CUST_CODE,NAME,CITY,STATE))) as MD5 FROM tcustmer;
    +----------------------------------+
    | MD5                              |
    +----------------------------------+
    | 9B1A3721FB80C9E75C136C5CFBB7FFC1 |
    | E0ACAC3ADA8E3AC75CE08CC32DDB4139 |
    | 4ECA8A64D252C69709344EE78BCB5923 |
    | D264438E50624428039DC6254851DB52 |
    | 1828B98ADF2E5866FA895DCB5B3A3833 |
    +----------------------------------+
    
    -- 由于后续需要使用到bit_xor做数值异或,将校验码截取前6位做比对
    SELECT left(upper(MD5(CONCAT_WS('',CUST_CODE,NAME,CITY,STATE))),6) as MD5 FROM tcustmer;
    +--------+
    | MD5    |
    +--------+
    | 9B1A37 |
    | E0ACAC |
    | 4ECA8A |
    | D26443 |
    | 1828B9 |
    +--------+
    
    -- 将16进制的MD5前6位字符串转换为10进制
    SELECT conv(left(upper(MD5(CONCAT_WS('',CUST_CODE,NAME,CITY,STATE))),6),16,10) as MD5 FROM tcustmer;
    +----------+
    | MD5      |
    +----------+
    | 10164791 |
    | 14724268 |
    | 5163658  |
    | 13788227 |
    | 1583289  |
    +----------+
    
    -- 最后对10进制的MD5值做异或算法生成唯一校验值
    SELECT bit_xor(conv(left(upper(MD5(CONCAT_WS('',CUST_CODE,NAME,CITY,STATE))),6),16,10)) as MD5 FROM tcustmer;
    +----------+
    | MD5      |
    +----------+
    | 16724203 |
    +----------+
    

    2. Oracle端数据校验

    由于Oracle端默认没有bit_xor函数,需要自行创建,且Oracle端MD5校验值是由DBMS_OBFUSCATION_TOOLKIT.MD5包生成,为了方便也重新创建函数进行封装

    2.1 Oracle列转行

    -- 查询DBA_TAB_COLUMNS生成拼接字段
    col table_name for a32
    col column_concat for a40
    
    -- 使用listagg聚合函数
    select table_name, listagg(COLUMN_NAME, '||') within group(order by column_id) column_concat
    from DBA_TAB_COLUMNS
    where OWNER = upper('scott')
    and table_name=upper('tcustmer')
    group by table_name;
    
    -- 输出结果示例
    TABLE_NAME			 COLUMN_CONCAT
    --------- ----------------------------------------
    TCUSTMER			 CUST_CODE||NAME||CITY||STATE
    

    2.2 创建Oracle端MD5函数

    -- 该函数只是为了使MD5的用法与MySQL一致
    CREATE OR REPLACE FUNCTION MD5(PASSWD IN VARCHAR2) RETURN VARCHAR2 IS
      RETVAL VARCHAR2(32);
    BEGIN
      RETVAL := UTL_RAW.CAST_TO_RAW(DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => PASSWD));
      RETURN RETVAL;
    END;
    /
    
    -- 调用测试
    col MD5 for a32
    select md5(CUST_CODE||NAME||CITY||STATE) as MD5 from TCUSTMER;
    
    -- 生成的结果与MySQL完全一致,符合预期
    MD5
    --------------------------------
    1828B98ADF2E5866FA895DCB5B3A3833
    D264438E50624428039DC6254851DB52
    4ECA8A64D252C69709344EE78BCB5923
    E0ACAC3ADA8E3AC75CE08CC32DDB4139
    9B1A3721FB80C9E75C136C5CFBB7FFC1
    

    2.3 创建Oracle端bit_xor函数

    create or replace type xor_type as object (
        cat_val number,
        static function ODCIAggregateInitialize(cs_ctx In Out xor_type) return number,
        member function ODCIAggregateIterate(self In Out xor_type,value in number) return number,
        member function ODCIAggregateMerge(self In Out xor_type,ctx2 In Out xor_type) return number,
        member function ODCIAggregateTerminate(self In Out xor_type,returnValue Out number,flags in number) return number
    )
    
    /
    
    create or replace type body xor_type is
      static function ODCIAggregateInitialize(cs_ctx IN OUT xor_type) return number
      is
      begin
          cs_ctx := xor_type(0);
          return ODCIConst.Success;
      end;
      member function ODCIAggregateIterate(self IN OUT xor_type,
                                           value IN number )
      return number
      is
      begin
          self.cat_val := value + self.cat_val - BITAND(value, self.cat_val) * 2;
    
          return ODCIConst.Success;
      end;
    
      member function ODCIAggregateTerminate(self IN Out xor_type,
                                             returnValue OUT number,
                                             flags IN number)
      return number
      is
      begin
          returnValue := self.cat_val;
          return ODCIConst.Success;
      end;
       
      member function ODCIAggregateMerge(self IN OUT xor_type,
                                         ctx2 IN Out xor_type)
      return number
      is
      begin
          self.cat_val := self.cat_val + ctx2.cat_val - BITAND(self.cat_val, ctx2.cat_val) * 2;
          return ODCIConst.Success;
      end;
    
    end;
      
    /
    
    CREATE OR REPLACE 
    FUNCTION bit_xor(input number)
    RETURN number
    PARALLEL_ENABLE AGGREGATE USING xor_type;
    
    /
    -- 调用验证
    SCOTT@zhenxing> select bit_xor(PRODUCT_PRICE) from TCUSTORD;
    BIT_XOR(PRODUCT_PRICE)
    ----------------------
    		167872
    
    
    -- 在MySQL端执行默认的bit_xor函数,对比结果一致
    root@localhost[demo]> select bit_xor(PRODUCT_PRICE) from TCUSTORD;
    +------------------------+
    | bit_xor(PRODUCT_PRICE) |
    +------------------------+
    |                 167872 |
    +------------------------+
    

    2.4 Oracle数据校验

    -- 生成MD5值
    SCOTT@zhenxing> col MD5 for a32
    SCOTT@zhenxing> select md5(CUST_CODE||NAME||CITY||STATE) as MD5 from TCUSTMER order by CUST_CODE;
    
    MD5
    --------------------------------
    9B1A3721FB80C9E75C136C5CFBB7FFC1
    E0ACAC3ADA8E3AC75CE08CC32DDB4139
    4ECA8A64D252C69709344EE78BCB5923
    D264438E50624428039DC6254851DB52
    1828B98ADF2E5866FA895DCB5B3A3833
    
    -- 后续需要使用到bit_xor做数值异或,将校验码截取前6位做比对
    SCOTT@zhenxing> select substr(md5(CUST_CODE||NAME||CITY||STATE),0,6) as MD5 from TCUSTMER order by CUST_CODE;
    
    MD5
    --------------------------------
    9B1A37
    E0ACAC
    4ECA8A
    D26443
    1828B9
    
    -- 将16进制的MD5前6位字符串转换为10进制
    SCOTT@zhenxing> col MD5 for 999999999999999999
    SCOTT@zhenxing> select to_number(substr(md5(CUST_CODE||NAME||CITY||STATE),0,6),'xxxxxxxxxx') as MD5 from TCUSTMER order by CUST_CODE;
    
    		MD5
    -------------------
    	   10164791
    	   14724268
    	    5163658
    	   13788227
    	    1583289
    
    -- 最后对10进制的MD5值做异或算法生成唯一校验值
    -- 对比MySQL端校验值,完全一致
    
    SCOTT@zhenxing> select bit_xor(to_number(substr(md5(CUST_CODE||NAME||CITY||STATE),0,6),'xxxxxxxxxx')) as MD5 from TCUSTMER order by CUST_CODE;
    
    		MD5
    -------------------
    	   16724203
    
    转载请说明出处 |QQ:327488733@qq.com
  • 相关阅读:
    【学习总结】Git学习-参考廖雪峰老师教程二-安装Git
    【学习总结】Git学习-参考廖雪峰老师教程一-Git简介
    【学习总结】vi/vim命令是使用
    【学习总结】Git学习-参考廖雪峰老师教程-总
    【kindle笔记】之 《鬼吹灯》-9-20
    【学习总结】win7下安装Ubuntu双系统的日常
    【kindle笔记】之 《明朝那些事儿》-2018-7-1
    【kindle笔记】之 《黑客微百科》-2018-6-17
    【kindle笔记】之 《恶意》-2018-4-20
    【kindle笔记】之 《活着》-2018-2-5
  • 原文地址:https://www.cnblogs.com/zhenxing/p/15102484.html
Copyright © 2011-2022 走看看