浙江地區數據下發均爲增量下發,只有數據發生改變的時候纔會下發,從接口層轉化大績效層的時候,有時關聯其他表會取不到數據,出於解決此問題,我們現場整理了一個批量生成MERGE語句的方法和調用的存儲過程。
首先我們來學習一下MERGE INTO語句是使用方法:
DB2中的Merge語句可以將一個表中的數據合併到另一個表中,在合併的同時可以根據條件進行插入、刪除、更新等操作。這個語句在我們PAS系統中多次轉換主鍵相同的數據時特別省時間。
語法如下:
MERGE INTO table_name alias1
USING (table|view|sub_query) alias2
ON (join condition)
WHEN MATCHED THEN
UPDATE table_name SET col1 = col_val1,col2 = col2_val
WHEN NOT MATCHED THEN
INSERT (column_list) VALUES (column_values)
關鍵字、參數的解答
into子句
在into子句中指定所要修改或者插入數據的目標表
using子句
在using子句中指定用來修改或者插入的數據源。數據源可以是表、視圖或者一個子查詢語句。
on子句
在on子句中指定執行插入或者修改的滿足條件。
when matched | not matched
用該子句通知數據庫如何對滿足或不滿足條件的結果做出相應的操作。可以使用以下的兩類子句。
merge_update子句
merge_update子句執行對目標表中的字段值修改。當在符合on子句條件的情況下執行。如果修改子句執行,則目標表上的修改觸發器將被觸發。
限制:當修改一個視圖時,不能指定一個default值
merge_insert 子句
merge_insert子句執行當不符合on子句條件時,往目標表中插入數據。如果插入子句執行,則目標表上插入觸發器將被觸發。
限制:當修改一個視圖時,不能指定一個default值
好,看完以上的基本語法後,我們來點乾貨吧。
JKSJ_CKZH的數據每天增量下發,我們要把它存在JXDX_CKZH_QL全量表中:執行一下命令即可。
merge into JKSJ_CKZH_QL as a
using (select b.ZHDH,b.ZZH,b.ZHHM,b.BZ,b.CPH,b.KMH,b.HSM,b.PZH,b.FHDH,b.JGDH,b.KHNM,b.KHH,b.KHRQ,b.QXRQ,b.DQRQ,b.XHRQ,b.ZHZT,b.ZHSX,b.QX,b.LLDH,b.NLL,b.KHJE,b.ZHYE,b.ZHBS,b.HYDH,b.CZYH
from JKSJ_CKZH b) bon a.ZHDH=b.ZHDHand a.ZZH=b.ZZH
when matched then
update set (a.ZHDH,a.ZZH,a.ZHHM,a.BZ,a.CPH,a.KMH,a.HSM,a.PZH,a.FHDH,a.JGDH,a.KHNM,a.KHH,a.KHRQ,a.QXRQ,a.DQRQ,a.XHRQ,a.ZHZT,a.ZHSX,a.QX,a.LLDH,a.NLL,a.KHJE,a.ZHYE,a.ZHBS,a.HYDH,a.CZYH)
=(b.ZHDH,b.ZZH,b.ZHHM,b.BZ,b.CPH,b.KMH,b.HSM,b.PZH,b.FHDH,b.JGDH,b.KHNM,b.KHH,b.KHRQ,b.QXRQ,b.DQRQ,b.XHRQ,b.ZHZT,b.ZHSX,b.QX,b.LLDH,b.NLL,b.KHJE,b.ZHYE,b.ZHBS,b.HYDH,b.CZYH)
when not matched then
insert (a.ZHDH,a.ZZH,a.ZHHM,a.BZ,a.CPH,a.KMH,a.HSM,a.PZH,a.FHDH,a.JGDH,a.KHNM,a.KHH,a.KHRQ,a.QXRQ,a.DQRQ,a.XHRQ,a.ZHZT,a.ZHSX,a.QX,a.LLDH,a.NLL,a.KHJE,a.ZHYE,a.ZHBS,a.HYDH,a.CZYH)
values (b.ZHDH,b.ZZH,b.ZHHM,b.BZ,b.CPH,b.KMH,b.HSM,b.PZH,b.FHDH,b.JGDH,b.KHNM,b.KHH,b.KHRQ,b.QXRQ,b.DQRQ,b.XHRQ,b.ZHZT,b.ZHSX,b.QX,b.LLDH,b.NLL,b.KHJE,b.ZHYE,b.ZHBS,b.HYDH,b.CZYH)
這麼長的一段是不是看傻眼了,但現在你不需要寫這一段了。因爲在浙江江山的項目我們已經把腳本寫好。以後增量下發的數據也可以用到。下面這個方法直接在TOAD青蛙裏面執行就可以了。
1.首先你要建一個跟增量表JKSJ_CKZH結構一樣的全量表JKSJ_CKZH_QL;
2查看與調用:單獨查看可用命令查看可執行如下:
SELECT MERGE_ADD_DATA('JKSJ_CKZH_QL', 'JKSJ_CKZH')FROM sysibm.sysdummy1;
或者在存儲過程中調用 :
declare c_sql varchar(11000);
set c_sql = MERGE_ADD_DATA(t_name, t_t_name);
prepare s1 from c_sql;
execute s1;
3.不單單是存款表可以這樣使用,所有的只要結構相同和有主鍵的表都可以這樣使用,如果在一個存儲過程循環調用上面那一段的話,即可完善所有表的全量表,另外個人認爲,此程序效率比SP_PASTRAN_CKZH要高一些,因爲裏面的邏輯都是一樣的,產品部可以根據項目如果是增量下發數據的,可以按此優化。
提高效率,應該從細節做起。另外附件,我也放入這個方法,每一行都加了註釋,裏面纔是精華哦,希望有興趣的Coder可以一起交流。
CREATE FUNCTION PAS.F_MERGE_ADD_DATA
( t_name varchar(50), --全量表表名
t_t_name varchar(50) --增量數據表名
)
RETURNS VARCHAR(10000)
LANGUAGE SQL
/*------------------------------------------------------------------------
公用函數:生成MERGER語句
功能描述:輸入全量表t_name和增量表t_t_name,返回增加增量數據到全量表的MERGE語句
作者:LIUHZ
日期:2016-11-27
項目名稱: 核心功能db2版
版本: v1.0
開發商:--
調用範例: SELECT F_MERGE_ADD_DATA('JKSJ_CKZH_QL', 'JKSJ_CKZH') FROM sysibm.sysdummy1;
------------------------------------------------------------------------*/
BEGIN
declare c_sql varchar(11000); --返回的sql
declare r_col varchar(3000); --全量表的列名 r表示result
declare r_col_b varchar(3000); --增量表的列名 r表示result
declare r_mainkey varchar(3000); --全量表和增量表的主鍵 r表示result
declare s_col varchar(200); --取列名的sql
declare s_mainkey varchar(300); --取主鍵的sql
--用於記錄主鍵的個數,
declare v_start int; --記錄substr()取數的開始位置
declare v_end int; --記錄sbustr()取數的結束位置
--聲明sql語句 s1和遊標 c1
declare s1 statement; --存放編譯的sql語句
declare c1 cursor for s1; --遊標
--行轉列,獲取增量表的列名。
set s_col = 'SELECT REPLACE(REPLACE(XML2CLOB(XMLAGG(XMLELEMENT(NAME A, ''b.''||name||'','',''''))),''<A>'',''''),''</A>'','''') '||
'from (select name from SYSIBM.SYSCOLUMNS where TBNAME='''||t_name||''' order by COLNO asc )' ;
--預編譯 s1
prepare s1 from s_col;
--將結果集放到 r_col_b (增量表的列名)
open c1;
fetch c1 into r_col_b;
close c1;
--去掉最右逗號
set r_col_b = left( r_col_b , length(r_col_b)-1);
--行轉列
set s_col = 'SELECT REPLACE(REPLACE(XML2CLOB(XMLAGG(XMLELEMENT(NAME A, ''a.''||name||'','',''''))),''<A>'',''''),''</A>'','''') from (select name from SYSIBM.SYSCOLUMNS where TBNAME= '''||t_name||''' order by COLNO asc )' ;
--將結果集放到 r_col (全量表的列名)
prepare s1 from s_col;
open c1;
fetch c1 into r_col;
close c1;
--去掉最右逗號
set r_col = left( r_col , length(r_col)-1);
--組合merge語句
set c_sql = 'merge into '|| t_name || ' as a using (select '||r_col_b||' from '||t_t_name||' b) b on ';
--SELECT REPLACE(REPLACE(XML2CLOB(XMLAGG(XMLELEMENT(NAME A, name||','))),'<A>',''),'</A>','') AS SELECTS
-- from (select name from SYSIBM.SYSCOLUMNS where TBNAME= 'JKSJ_CKZH' and KEYSEQ is not null order by keyseq asc)
--獲取主鍵,但PAS系統一般不聲明primaryKey,只將我們的認爲的主鍵聲明爲not null。
set s_mainkey = 'SELECT REPLACE(REPLACE(XML2CLOB(XMLAGG(XMLELEMENT(NAME A, name||'','',''''))),''<A>'',''''),''</A>'','''') from (select name from SYSIBM.SYSCOLUMNS where TBNAME='''||t_name||''' and NULLS=''N'' order by NULLS asc)' ;
--將結果集放到 r_mainkey (全量表和增量表關聯的主鍵)
prepare s1 from s_mainkey;
open c1;
fetch c1 into r_mainkey;
close c1;
--去掉最右逗號
set r_mainkey = left( r_mainkey , length(r_mainkey)-1);
--組合 on 後面的條件(其實就是主鍵關聯) 到 c_sql
set v_start = 1;
set v_end = locate(',',r_mainkey);
while v_end > 0
do
set c_sql = c_sql || ' a.'||substr(r_mainkey,v_start,v_end-v_start) || '=b.'||substr(r_mainkey,v_start,v_end-v_start)||' and ';
set v_start = v_end+1;
set v_end = locate(',',r_mainkey,v_start);
end while;
--組合主鍵中最後一個主鍵
set c_sql = c_sql || ' a.'||substr(r_mainkey,v_start) || '=b.'||substr(r_mainkey,v_start);
--組合merge語句的更新語句和插入語句
set c_sql = c_sql || ' when matched then update set ('||r_col||')=('||r_col_b||') when not matched then insert ('||r_col||' ) values ('||r_col_b||')';
call SP_PASSYS_XTRZ ('0',v_proc_name,c_sql);
--返回MERGE語句
RETURN c_sql;
-- RETURN s_mainkey;
END