CREATE OR REPLACE PROCEDURE UPDATE_CRDT_JV IS
BEGIN
UPDATE GL_DISTRIBUTION
SET GL_DATE = (SELECT ADJ_DATE FROM ADJUSTMENTS WHERE
ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
WHERE TR_TYPE = 'ADJST';
UPDATE GL_DISTRIBUTION
SET GL_DATE = (SELECT PARTY_ADJ_DATE FROM PARTY_ADJUSTMENT
WHERE PARTY_ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
WHERE TR_TYPE = 'PRTAJ';
UPDATE GL_DISTRIBUTION
SET GL_DATE = (SELECT VEN_PAY_VOU_DATE FROM PAYMENTS_TO_VENDORS WHERE
VEN_PAY_VOU_NUMBER = TO_NUMBER(TR_NUMBER))
WHERE TR_TYPE = 'CRPAY';
UPDATE GL_DISTRIBUTION
SET GL_DATE = (SELECT CHEQUE_DATE FROM SYS_PAYMENTS_HEADER WHERE
REF_NUMBER = TO_NUMBER(TR_NUMBER))
WHERE TR_TYPE = 'SYSPY';
UPDATE GL_DISTRIBUTION
SET GL_DATE = (SELECT POSTED_DATE FROM PURCHASE_INVOICE_HEADER WHERE
POSTED_DATE IS NOT NULL AND PIV_NUMBER = TO_NUMBER(TR_NUMBER))
WHERE TR_TYPE = 'CRINV';
UPDATE GL_dISTRIBUTION
SET GL_dATE = (SELECT DOC_dATE FROM REVERSE_HISTORY
WHERE TR_NUMBER = TO_NUMBER(GL_DISTRIBUTION.TR_NUMBER)
AND DOC_dATE IS NOT NULL AND TR_TYPE IN ('SYSPY','CRPAY'))
WHERE TR_TYPE IN ('RSYSPY','RCRPAY');
commit;
UPDATE_INV_DET;
END;
需要超过15分钟才能更新数据库。 现在我通过在SQL PLUS中使用以下查询来更新它:
EXECUTE UPDATE_CRDT_JV;
如果有任何人知道这个问题的解决方案,请帮助我
答案 0 :(得分:4)
我同意已经给出的建议,以开始计算代码花费时间的位置。但是,你的情况非常普遍,我认为我认识到这种情况:你已经编写了更新语句,以便为该类型的GL_DISTRIBUTION的每一行访问其他表。
解决方案是重写更新语句,我认为有效地实现这两种可能性:
1)更新一个select语句(UPDATE(SELECT ...)SET ... WHERE ...)。这需要一些唯一的键约束或使用BYPASS_UJVC提示。
2)使用MERGE语句。
下面您将看到如何使用单个合并语句重写代码的示例。我期待大的性能提升,因为现在使用每个表的单个外部联接,而不是GL_DISTRIBUTION表中的每一行,对其他表的访问进行一次。
这个例子。测试数据:
SQL> create table gl_distribution (tr_number, tr_type, gl_date)
2 as
3 select '1', 'ADJST', date '2011-01-01' from dual union all
4 select '2', 'ADJST', null from dual union all
5 select '3', 'PRTAJ', date '2011-01-01' from dual union all
6 select '4', 'SYSPY', date '2011-01-01' from dual union all
7 select '5', 'RCRPAY', date '2011-01-01' from dual
8 /
Table created.
SQL> create table adjustments (adj_number, adj_date)
2 as
3 select 1, sysdate from dual union all
4 select 2, sysdate from dual
5 /
Table created.
SQL> create table party_adjustment (party_adj_number, party_adj_date)
2 as
3 select 3, sysdate from dual union all
4 select 33, sysdate from dual
5 /
Table created.
SQL> create table payments_to_vendors (ven_pay_vou_number, ven_pay_vou_date)
2 as
3 select 34, sysdate from dual
4 /
Table created.
SQL> create table sys_payments_header (ref_number,cheque_date)
2 as
3 select 4, sysdate from dual
4 /
Table created.
SQL> create table purchase_invoice_header (piv_number,posted_date)
2 as
3 select 35, sysdate from dual
4 /
Table created.
SQL> create table reverse_history (tr_number,doc_date,tr_type)
2 as
3 select 5, sysdate, 'CRPAY' from dual
4 /
Table created.
SQL>
您的程序(用于比较):
SQL> CREATE OR REPLACE PROCEDURE UPDATE_CRDT_JV
2 IS
3 BEGIN
4 UPDATE GL_DISTRIBUTION
5 SET GL_DATE = (SELECT ADJ_DATE FROM ADJUSTMENTS WHERE ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
6 WHERE TR_TYPE = 'ADJST'
7 ;
8 UPDATE GL_DISTRIBUTION
9 SET GL_DATE = (SELECT PARTY_ADJ_DATE FROM PARTY_ADJUSTMENT
10 WHERE PARTY_ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
11 WHERE TR_TYPE = 'PRTAJ'
12 ;
13 UPDATE GL_DISTRIBUTION
14 SET GL_DATE = (SELECT VEN_PAY_VOU_DATE FROM PAYMENTS_TO_VENDORS
15 WHERE VEN_PAY_VOU_NUMBER = TO_NUMBER(TR_NUMBER))
16 WHERE TR_TYPE = 'CRPAY'
17 ;
18 UPDATE GL_DISTRIBUTION
19 SET GL_DATE = (SELECT CHEQUE_DATE FROM SYS_PAYMENTS_HEADER WHERE
20 REF_NUMBER = TO_NUMBER(TR_NUMBER))
21 WHERE TR_TYPE = 'SYSPY'
22 ;
23 UPDATE GL_DISTRIBUTION
24 SET GL_DATE = (SELECT POSTED_DATE FROM PURCHASE_INVOICE_HEADER WHERE
25 POSTED_DATE IS NOT NULL AND PIV_NUMBER = TO_NUMBER(TR_NUMBER))
26 WHERE TR_TYPE = 'CRINV'
27 ;
28 UPDATE GL_dISTRIBUTION
29 SET GL_dATE = (SELECT DOC_dATE FROM REVERSE_HISTORY
30 WHERE TR_NUMBER = TO_NUMBER(GL_DISTRIBUTION.TR_NUMBER)
31 AND DOC_dATE IS NOT NULL AND TR_TYPE IN ('SYSPY','CRPAY'))
32 WHERE TR_TYPE IN ('RSYSPY','RCRPAY')
33 ;
34 --commit;
35 --UPDATE_INV_DET;
36 END;
37 /
Procedure created.
SQL>
我的建议:
SQL> create procedure new_update_crdt_jv
2 as
3 begin
4 merge into gl_distribution d
5 using ( select to_number(d.tr_number) tr_number
6 , coalesce
7 ( a.adj_date
8 , pa.party_adj_date
9 , pv.ven_pay_vou_date
10 , sph.cheque_date
11 , pih.posted_date
12 , rh.doc_date
13 ) new_date
14 from gl_distribution d
15 left outer join adjustments a
16 on to_number(d.tr_number) = a.adj_number
17 and d.tr_type = 'ADJST'
18 left outer join party_adjustment pa
19 on to_number(d.tr_number) = pa.party_adj_number
20 and d.tr_type = 'PRTAJ'
21 left outer join payments_to_vendors pv
22 on to_number(d.tr_number) = pv.ven_pay_vou_number
23 and d.tr_type = 'CRPAY'
24 left outer join sys_payments_header sph
25 on to_number(d.tr_number) = sph.ref_number
26 and d.tr_type = 'SYSPY'
27 left outer join purchase_invoice_header pih
28 on to_number(d.tr_number) = pih.piv_number
29 and d.tr_type = 'CRINV'
30 left outer join reverse_history rh
31 on to_number(d.tr_number) = rh.tr_number
32 and rh.tr_type in ('SYSPY','CRPAY')
33 and d.tr_type in ('RSYSPY','RCRPAY')
34 ) n
35 on ( d.tr_number = n.tr_number)
36 when matched then
37 update set d.gl_date = n.new_date
38 ;
39 end new_update_crdt_jv;
40 /
Procedure created.
SQL>
让我们运行你的程序:
SQL> select * from gl_distribution
2 /
T TR_TYP GL_DATE
- ------ -------------------
1 ADJST 01-01-2011 00:00:00
2 ADJST
3 PRTAJ 01-01-2011 00:00:00
4 SYSPY 01-01-2011 00:00:00
5 RCRPAY 01-01-2011 00:00:00
5 rows selected.
SQL> exec update_crdt_jv
PL/SQL procedure successfully completed.
SQL> select * from gl_distribution
2 /
T TR_TYP GL_DATE
- ------ -------------------
1 ADJST 31-03-2011 14:41:19
2 ADJST 31-03-2011 14:41:19
3 PRTAJ 31-03-2011 14:41:19
4 SYSPY 31-03-2011 14:41:19
5 RCRPAY 31-03-2011 14:41:19
5 rows selected.
SQL> rollback
2 /
Rollback complete.
SQL>
我的程序返回相同的结果:
SQL> exec new_update_crdt_jv
PL/SQL procedure successfully completed.
SQL> select * from gl_distribution
2 /
T TR_TYP GL_DATE
- ------ -------------------
1 ADJST 31-03-2011 14:41:19
2 ADJST 31-03-2011 14:41:19
3 PRTAJ 31-03-2011 14:41:19
4 SYSPY 31-03-2011 14:41:19
5 RCRPAY 31-03-2011 14:41:19
5 rows selected.
希望这有帮助。
的问候,
罗布。
答案 1 :(得分:3)
此问题的解决方案是:
如果您更喜欢猜测,那么您可能想尝试以下任何一项:
将多个UPDATE组合到单个UPDATE语句中,例如使用@Aklopper所示的CASE条件。
使用MERGE而不是UPDATE来避免相关子查询。可能会更好,也许不会。
查看在显示的过程结束时调用的UPDATE_INV_DET过程。
答案 2 :(得分:2)
我来自SQL Server环境,这样的CASE UPDATE语句也不会帮助你(在SQL中使用UPDATE CASE语句的例子(不知道Oracle是否有等效的方法):
UPDATE titles
SET GL_DATE=
CASE
WHEN TR_TYPE = 'ADJST' THEN (SELECT ADJ_DATE FROM ADJUSTMENTS WHERE ADJ_NUMBER = TO_NUMBER(TR_NUMBER) END
WHEN TR_TYPE = 'PRTAJ'' THEN (SELECT PARTY_ADJ_DATE FROM PARTY_ADJUSTMENT
WHERE PARTY_ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
END
ELSE price
END