觸發器進行資料校驗(去重、異常處理)
觸發器進行資料校驗(去重、異常處理)
目錄一、前提
根據地市企業名稱和統一社會信用程式碼不一致,以及來源部門和統一社會信用程式碼不一致導致的資料錯誤率上升。來如何解決?
下面的流程圖為大致的解決思路:
二、思路
按照如上的來,觸發器裡面核驗的寫法可以如下:
如下引數:
(v_count 用來儲存查詢後的uscc的值)
(T_CS20201119 企業或部門核查表,插入的資料根據name去匹配uscc)
create or replace trigger 許可觸發器 before INSERT or UPDATE on t_xzxklqx referencing OLD AS OLD NEW AS NEW for each row declare v_count varchar2(18); begin if inserting then select uscc into v_count from T_CS20201119 t where name=:new.XK_XZJG; if (:new.XK_XKJGDM != v_count) then RAISE_APPLICATION_ERROR(-20000,'部門統一社會信用程式碼錯誤'); end if; end if; end 許可觸發器;
上述觸發器為:當插入資料的時候,根據插入的許可機構名稱
去匹配核驗表
(企業和機構部門表)中的名稱,從而取核驗表
中的uscc(統一社會信用程式碼)。在根據取出來的uscc賦值給v_count 對插入的許可機構的編碼進行匹配,當不匹配的時候,會出錯‘部門統一社會信用程式碼錯誤’。
三、重複等問題
但是這時候會出現以下問題:
需要完整且實時更新的企業和部門的核驗表?
核驗表有重複資料怎麼辦?
當傳輸資料中的企業不存在核驗表的時候,跳過核驗(阻止報錯後續說明)?
1A:針對第一個問題,目前只能對接工商的企業資訊表和編辦的部門機構統一社會資訊程式碼表。
2A:針對第二個問題。當有核驗表重複的資料的時候,一個查詢會返回多個結果,進行核驗的時候會出現多個uscc對應一個的情況從而會報錯。通俗點就是聯誼的時候,不是1對1,而是好幾個對一個,無法相匹配。所以我們可以去重查詢,只查詢核驗表
select uscc into v_count
from (select row_number() over(partition by NAME order by 時間欄位 desc) a,
t.NAME,t.USCC
from T_CS20201119 t
where 1 = 1 )
where a = 1
and name=:new.XK_XZJG;
新增了去重查詢:根據企業名稱進行時間欄位倒序排列,取第一個重複企業的企業資料。
3A: 按照回答二的語句來看,解決了重複的資料,但是當我們傳一條核查表裡面沒有的企業
沒有找到任何資料原因來自: 當我們查詢核查表的時候,如果沒找到的話,會返回無值,並不是返回空值,
。所以會導致未找到任何資料。
在思考之後,只增加了一個用法,如下:
select min(uscc)
into v_count
from (select row_number() over(partition by NAME order by 時間欄位 desc) a, t.NAME,t.USCC
from T_CS20201119 t
where 1 = 1 )
where a = 1 and name=:new.XK_XZJG;
我在uscc增加了min(),不能查詢到企業的時候,只返回空值,從而跳過了‘未找到任何資料’
這個錯誤。
且經過多次測試,沒有任何異常
測試方法:一共三個測試用例:
測試用例 | 情況 | 結果 |
---|---|---|
NAME:安徽省臨泉縣發展改革委 USCC: 11341221003171913L |
符合 企業(部門)核查表的NAME和USCC | 可以正常匯入 |
NAME:安徽省臨泉縣發展改革委 USCC: 1134122100317 |
NAME能匹配上企業(部門)核查表,但是USCC不匹配 | 匯入失敗,報錯資訊為:ORA-20000: 部門統一社會信用程式碼錯誤 正常的匯入失敗報錯資訊 |
NAME:安徽省臨泉縣發展改革委123 USCC: 11341221003171913L |
NAME能不匹配上企業(部門)核查表。 | 可以正常匯入,當傳輸資料中的企業不存在核驗表的時候,跳過核驗 |
所以整合上訴的要求,該判斷語句如下:
select min(uscc) into v_count
from (select row_number() over(partition by NAME order by 時間欄位 desc) a, t.NAME,t.USCC from T_CS20201119 t where 1 = 1 )
where a = 1 and name=:new.XK_XZJG;
if (:new.XK_XKJGDM != v_count) then
RAISE_APPLICATION_ERROR(-20000,'部門統一社會信用程式碼錯誤');
end if;
填報我測試多次都毫無問題。
四、其餘方法與思考
但是這個我難以自說其圓,原因是,當部門無法在核查表中查詢的時候,返回的值是空值。但是按照下一步 if(:new.XK_XKJGDM != v_count)這個來看,:new.XK_XKJGDM是肯定不等於空值的,肯定會報錯誤資訊,但是實際上。並沒有出錯,才疏學淺,不知道怎麼回事,我百度也無結果。但我個人覺得不嚴謹,有知道原理的可以告知我。
所以語句我經過了更改如下:標紅為更改處
select nvl
(min(uscc),0
) into v_count
from (select row_number() over(partition by NAME order by 時間欄位 desc) a, t.NAME,t.USCC from T_CS20201119 t where 1 = 1 ) where a = 1 and name=:new.XK_XZJG;
if(v_count!=0) then
if (:new.XK_XKJGDM != v_count) then
RAISE_APPLICATION_ERROR(-20000,'部門統一社會信用程式碼錯誤');
end if;
end if;
函式NVL的語法為:NVL(eExpression1, eExpression2) ,如果 eExpression1 的計算結果為 null 值,則 NVL( ) 返回 eExpression2。如果 eExpression1 的計算結果不是 null 值,則返回 eExpression1。
但是還得加上min() ,因為不加上min()的話,就像這樣:nvl(uscc,0),企業不存在核查表的時候,返回的無值,而不是空值,查詢結果沒辦法替換成0,會報錯‘未找到任何資料’。
當為空值的時候,賦予v_count =0
,不做任何判斷,當v_count不等於0的時候
,則就判斷上傳資料的企業(部門)編碼是否與核查表一致。不一致則會報錯提醒。
另外還有一種方法,no_data_found異常處理,和min的結果一樣,獲取到null值,直接跳過判斷:語句如下,修改處標紅:
begin
select uscc
into v_count
from (select row_number() over(partition by NAME order by sj desc) a, t.NAME,t.USCC from T_CS20201119 t where 1 = 1 ) where a = 1 and name=:new.XK_XZJG;
exception
when NO_DATA_FOUND then
v_count := null;
end;
if (:new.XK_XKJGDM != v_count) then
RAISE_APPLICATION_ERROR(-20000,'部門統一社會信用程式碼錯誤');
end if;
去掉了min(),當語句查詢的時候,核查表中沒有該企業的時候,會查出無值,正常情況下會報錯‘未找到任何資料’
。但是這時候用no_data_found異常處理。給他賦予為null的值,從而跳過核驗。只要報了NO_DATA_FOUND異常,都會立即stop,要麼跳轉到exception,要麼返回null,不再繼續執行。
方法應該還有很多。
目的就是如何核驗企業名稱和統一社會信用程式碼是否和正確的核驗表是否一致,用來保證資料質量。
重要的是我不知道就是為什麼賦值為空值和null的時候,會跳過後續的判斷,我個人理解要判斷,也許可能我陷入到判斷的固定思維。