Oracle嵌套xml解析
Posted
技术标签:
【中文标题】Oracle嵌套xml解析【英文标题】:Oracle nested xml parsing 【发布时间】:2020-10-01 07:40:34 【问题描述】:我有一个 excel,在使用应用程序导入 excel 时,我将其转换为 XML 字符串,然后将其发送到 Oracle 中的程序。下面的代码是我的程序。
PROCEDURE SP_UPLOAD_KALEMS(P_REFCURSOR OUT SYS_REFCURSOR,P_YEAR IN NUMBER,P_MONTH IN NUMBER,P_KALEMS IN CLOB) IS personelId NUMBER; BEGIN
SAVEPOINT start_tran;
DELETE FROM HRANALY.WAGE_ACTUAL WA WHERE WA.A_MONTH=P_MONTH AND WA.A_YEAR=P_YEAR;
FOR r IN (
select * FROM XMLTABLE('/ArrayOfBaseUpload/BaseUpload'PASSING xmltype(P_KALEMS)
COLUMNS
SICIL NUMBER PATH './SICIL',
SAP_ORG_KOD NUMBER PATH './SAP_ORG_KOD' ,
POSITION VARCHAR2(100) PATH './POSITION',
IS_INFO VARCHAR2(10) PATH './IS',
FABRIC VARCHAR2(10) PATH './FABRIC',
COST_CENTER NUMBER PATH './COST_CENTER' ,
PERSONE_TYPE VARCHAR2(10) PATH './PERSONE_TYPE',
UCRET_TIP VARCHAR2(10) PATH './UCRET_TIP' ,
BELGE_KOD VARCHAR2(200) PATH './BELGE_KOD',
TUTAR NUMBER PATH './TUTAR' ,
SGK_GUN NUMBER PATH './SGK_GUN' ,
SSK_MATRAH NUMBER PATH './SSK_MATRAH' ,
SS_MATRAH NUMBER PATH './SS_MATRAH' ,
YASAL_NET NUMBER PATH './YASAL_NET' ,
ODEME_TUTARI NUMBER PATH './ODEME_TUTARI'
) PERSONELS
)LOOP
personelId:=HRANALY.SEQ_WAGE_MAIN.nextval;
INSERT INTO HRANALY.WAGE_ACTUAL(ID,SICIL,SAP_ORG_KOD, POSITION,IS_INFO,FABRIC,COST_CENTER,PERSONE_TYPE,A_MONTH,A_YEAR,UCRET_TIP,BELGE_KOD,
TUTAR,SGK_GUN,SSK_MATRAH,SS_MATRAH,YASAL_NET,ODEME_TUTARI)
VALUES(personelId,r.SICIL,r.SAP_ORG_KOD,r.POSITION,r.IS_INFO,r.FABRIC,r.COST_CENTER,r.PERSONE_TYPE,P_MONTH,P_YEAR,R.UCRET_TIP,r.BELGE_KOD,
r.TUTAR,r.SGK_GUN,r.SSK_MATRAH,r.SS_MATRAH,r.YASAL_NET,r.ODEME_TUTARI);
FOR p IN (
select * FROM XMLTABLE('/ArrayOfBaseUpload/BaseUpload/DETAILS/DetayUpload'PASSING xmltype(P_KALEMS)
COLUMNS CODE varchar2(100) PATH './CODE',
SICIL NUMBER PATH './../../SICIL',
AMOUNT NUMBER PATH './AMOUNT') kalems
)
LOOP
IF r.SICIL=p.SICIL THEN
INSERT INTO HRANALY.WAGE_ACTUAL_DETAIL(ID,REF_WAGE,AMOUNT,KALEM_KOD,A_MONTH,A_YEAR)
VALUES(HRANALY.SEQ_WAGE_DETAIL.nextval,personelId,p.AMOUNT,p.CODE,P_MONTH,P_YEAR);
END IF;
END LOOP;
END LOOP;
COMMIT;
OPEN P_REFCURSOR FOR
SELECT 'SUCCESS' AS RESULT FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO start_tran;
OPEN P_REFCURSOR FOR
SELECT 'ERROR' AS RESULT FROM DUAL;
RAISE;
END ;
我的问题是我在 Excel 中有大约 2000 行和大约 40 列(可能或多或少)。其中 15 个是静态列,保存在 HRANALY.WAGE_ACTUAL
表中,其他列是动态的并插入到 HRANALY.WAGE_ACTUAL_DETAIL
中。
SICIL
是唯一的,例如用户的身份代码。对于一个sicil,可以插入多个细节到HRANALY.WAGE_ACTUAL_DETAIL
我的代码需要太多时间来插入所有变量。我想更快地优化这段代码。我怎样才能加快速度。
我的xml喜欢
<ArrayOfBaseUpload>
<BaseUpload>
<SICIL>1</SICIL>
<SAP_ORG_KOD>500</SAP_ORG_KOD>
<POSITION>Operator</POSITION>
<IS>TR - Dikim </IS>
<FABRIC>IZ01</FABRIC>
<COST_CENTER>100</COST_CENTER>
<PERSONE_TYPE>T2</PERSONE_TYPE>
<UCRET_TIP>Brüt</UCRET_TIP>
<BELGE_KOD>1</BELGE_KOD>
<TUTAR>10.00</TUTAR>
<SGK_GUN>30</SGK_GUN>
<SSK_MATRAH>100</SSK_MATRAH>
<SS_MATRAH>100</SS_MATRAH>
<YASAL_NET>100</YASAL_NET>
<ODEME_TUTARI>100</ODEME_TUTARI>
<DETAILS>
<DetayUpload><CODE>TEMEL_UCRET</CODE><AMOUNT>100</AMOUNT></DetayUpload>//here there can ve 40 data like that
</DETAILS>
</BaseUpload>
</ArrayOfBaseUpload>
提前致谢
【问题讨论】:
你知道程序的哪一部分是慢的,所以我们知道应该关注什么吗? (找出问题的好方法是使用 PL/SQL 分析。或者您可以简单地注释掉过程的某些部分并重新运行。)例如,如果只有INSERT
语句很慢,那么提高性能的简单方法是将结果保存在集合中并使用FORALL
一次写入多行。如果读取和写入都很慢,将循环重新写入单个 SQL 语句可能是有意义的。
减速原因可以是嵌套循环。第一个循环包含大约 2000 个数据,第二个循环包含大约 60000 个数据(如果每个数据有 30 个详细信息),那么这需要太多时间,并且这里还有 if 条件来检查是否相同的 uniqe SICIL 。这可能是时间的主要原因@JonHeller
对于性能问题,了解每行代码的运行时间很重要,而不仅仅是猜测。没有这些信息,很容易出现强迫性调整障碍并优化无关紧要的事情。通过分析和诸如“行 X 占运行时间的 Y%”之类的信息,我们可以确定我们只是在解决真正重要的问题。
【参考方案1】:
编写慢速 SQL 的最佳方法是将 insert/update/delete
放入一个循环中,一次更改一行。
如果您想要快速 SQL,请使用一条语句来更改所有行。用两个 insert-select
语句替换循环应该会加快速度:
insert into hranaly.wage_actual(
id,sicil,sap_org_kod, position,is_info,fabric,cost_center,persone_type,a_month,a_year,ucret_tip,belge_kod,
tutar,sgk_gun,ssk_matrah,ss_matrah,yasal_net,odeme_tutari
)
select hranaly.seq_wage_main.nextval, sicil,sap_org_kod,
position,is_info,fabric,cost_center,persone_type,
p_month,p_year,ucret_tip,belge_kod,tutar,sgk_gun,
ssk_matrah,ss_matrah,yasal_net,odeme_tutari
from xmltable('/ArrayOfBaseUpload/BaseUpload' passing xmltype( p_kalems )
columns
sicil number path './SICIL',
sap_org_kod number path './SAP_ORG_KOD' ,
position varchar2(100) path './POSITION',
is_info varchar2(10) path './IS',
fabric varchar2(10) path './FABRIC',
cost_center number path './COST_CENTER' ,
persone_type varchar2(10) path './PERSONE_TYPE',
ucret_tip varchar2(10) path './UCRET_TIP' ,
belge_kod varchar2(200) path './BELGE_KOD',
tutar number path './TUTAR' ,
sgk_gun number path './SGK_GUN' ,
ssk_matrah number path './SSK_MATRAH' ,
ss_matrah number path './SS_MATRAH' ,
yasal_net number path './YASAL_NET' ,
odeme_tutari number path './ODEME_TUTARI'
);
insert into hranaly.wage_actual_detail(id,ref_wage,amount,kalem_kod,a_month,a_year)
select hranaly.seq_wage_detail.nextval,wa.id,
p.amount,p.code,p_month,p_year
from hranaly.wage_actual wa
join xmltable('/ArrayOfBaseUpload/BaseUpload/DETAILS/DetayUpload' passing xmltype ( p_kalems )
columns
code varchar2(100) path './CODE',
sicil number path './../../SICIL',
amount number path './AMOUNT'
) kalems
on wa.a_month= p_month
and wa.a_year=p_year
and wa.sicil=kalems.sicil;
您甚至可以将其变成一个多表插入 (insert all
),这可能会更快。不过,如果上述更改仍然太慢,我只会考虑这一点。
【讨论】:
以上是关于Oracle嵌套xml解析的主要内容,如果未能解决你的问题,请参考以下文章