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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章