oracle update query [duplicate] - oracle

This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
Oracle Multiple update Query
I have a query
Select item_code,comp_code from item;
which returns
item_code, comp_code
912001 01
912001 04
912002 01
912002 02
912002 03
912003 01
and i have three values for comp_code for each item. suppose comp_1,comp_2,comp_3
now i want to update the table with each item code will have these three values. ie, there will be three entry for each item with comp_code value as comp_1,comp_2,comp_3 like below o/p
item_code, comp_code
912001 comp_1
912001 comp_2
912001 comp_3
912002 comp_1
912002 comp_2
912002 comp_3
912003 comp_1
912003 comp_2
912003 comp_3
How can write a single query which select and update these values

I'm not sure I quite follow what you want.. but to get from figure A to figure B, you could do the following.
Create a holding table with the new values
Drop the old table
Rename the holding table.
This of course does not take into account indexes, permissions, etc...
SQL> #so_test
SQL> DROP
2 TABLE SO_TEST;
Table dropped.
SQL>
SQL> CREATE
2 TABLE SO_TEST
3 (
4 ITEM_CODE NUMBER
5 , COMP_CODE VARCHAR2 (10)
6 );
Table created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912001
6 ,'01'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912001
6 ,'04'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912002
6 ,'01'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912002
6 ,'02'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912002
6 ,'03'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912003
6 ,'01'
7 );
1 row created.
SQL>
SQL> CREATE
2 TABLE SO_TEST_NEW AS
3 SELECT
4 A.ITEM_CODE AS ITEM_CODE
5 , 'comp_'
6 || B.N AS COMP_CODE
7 FROM
8 (
9 SELECT
10 ITEM_CODE
11 FROM
12 SO_TEST
13 GROUP BY
14 ITEM_CODE
15 )
16 A
17 , (
18 SELECT
19 ROWNUM AS N
20 FROM
21 (
22 SELECT
23 1 X
24 FROM
25 DUAL
26 CONNECT BY LEVEL <= 3
27 )
28 )
29 B
30 ORDER BY
31 A.ITEM_CODE;
Table created.
SQL>
SQL> DROP
2 TABLE SO_TEST;
Table dropped.
SQL>
SQL> ALTER TABLE SO_TEST_NEW RENAME TO SO_TEST;
Table altered.
SQL>
SQL> SELECT
2 *
3 FROM
4 SO_TEST;
ITEM_CODE COMP_CODE
---------- ---------------------------------------------
912001 comp_1
912001 comp_2
912001 comp_3
912002 comp_1
912002 comp_3
912002 comp_2
912003 comp_1
912003 comp_3
912003 comp_2
9 rows selected.
SQL>

Related

how to convert column value to multiple insert rown oracle cursor

I am trying to copy value from our old db to new db where there is a change in the table structure.
Below is the structure of the table
Table1
Table1ID, WheelCount, BlindCount, OtherCount
For eg values of table 1 is like below
Table1ID, 1,2,5
Table1 is now changed to TableNew with the below
TableNewID, DisableID , Quantity.
So the value should be
TableNewID1, 1,1 here 1= WheelCount from table1
TableNewID2, 2,2 here 2= BlindCount
TableNewID3, 3,5 here 5= OtherCount
how to write a cursor to transform table1 value to the new table tableNew structure.
Table1
Table1ID WheelCount BlindCount OtherCount
1 1 2 5
2 8 10 15
A master table defined to map disableid
DisableID Type
1 wheelCount
2 blindcount
3 otherCount
Expected structure
ID **Table1ID** **DISABLEID** QUANTITY
1 1 1 1
2 1 2 2
3 1 3 5
4 2 1 8
5 2 2 10
6 2 3 15
The simplest is a UNION ALL for each column you want to turn into a row.
insert into tablenew
select table1id,1,wheelcount from table1
union all
select table1id,2,blindcount from table1
union all
select table1id,3,othercount from table1
There are other, sleeker methods for avoiding multiple passes on the first table, in case it's huge.
This is how I understood it.
Current table contents:
SQL> SELECT * FROM table1;
TABLE1ID WHEELCOUNT BLINDCOUNT OTHERCOUNT
---------- ---------- ---------- ----------
1 1 2 5
2 8 10 15
Prepare new table:
SQL> CREATE TABLE tablenew
2 (
3 id NUMBER,
4 table1id NUMBER,
5 disableid NUMBER,
6 quantity NUMBER
7 );
Table created.
Sequence (will be used to populate tablenew.id column):
SQL> CREATE SEQUENCE seq_dis;
Sequence created.
Trigger (which actually populates tablenew.id):
SQL> CREATE OR REPLACE TRIGGER trg_bi_tn
2 BEFORE INSERT
3 ON tablenew
4 FOR EACH ROW
5 BEGIN
6 :new.id := seq_dis.NEXTVAL;
7 END;
8 /
Trigger created.
Copy data:
SQL> INSERT INTO tablenew (table1id, disableid, quantity)
2 SELECT table1id, 1 disableid, wheelcount AS quantity FROM table1
3 UNION ALL
4 SELECT table1id, 2 disableid, blindcount AS quantity FROM table1
5 UNION ALL
6 SELECT table1id, 3 disableid, othercount AS quantity FROM table1;
6 rows created.
Result:
SQL> SELECT *
2 FROM tablenew
3 ORDER BY table1id, disableid;
ID TABLE1ID DISABLEID QUANTITY
---------- ---------- ---------- ----------
1 1 1 1
3 1 2 2
5 1 3 5
2 2 1 8
4 2 2 10
6 2 3 15
6 rows selected.

For each company in a table Company, I want to create a random number of rows between 50 and 250 in table Employee in PL/SQL?

For each company entry in a table Company, I want to create a random number of rows between 50 and 250 in table Employee in PL/SQL.
Here's one option, based on data in Scott's sample schema.
Departments (that's your company):
SQL> SELECT * FROM dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Target table:
SQL> CREATE TABLE employee
2 (
3 deptno NUMBER,
4 empno NUMBER PRIMARY KEY,
5 ename VARCHAR2 (10),
6 salary NUMBER
7 );
Table created.
Sequence (for primary key values):
SQL> CREATE SEQUENCE seq_e;
Sequence created.
Here's the procedure: for each department, it creates L_ROWS number of rows (line #8) (I restricted it to a number between 1 and 5; your boundaries would be 50 and 250). It also creates random names (line #16) and salaries (line #17):
SQL> DECLARE
2 l_rows NUMBER;
3 BEGIN
4 DELETE FROM employee;
5
6 FOR cur_d IN (SELECT deptno FROM dept)
7 LOOP
8 l_rows := ROUND (DBMS_RANDOM.VALUE (1, 5));
9
10 INSERT INTO employee (deptno,
11 empno,
12 ename,
13 salary)
14 SELECT cur_d.deptno,
15 seq_e.NEXTVAL,
16 DBMS_RANDOM.string ('x', 7),
17 ROUND (DBMS_RANDOM.VALUE (100, 900))
18 FROM DUAL
19 CONNECT BY LEVEL <= l_rows;
20 END LOOP;
21 END;
22 /
PL/SQL procedure successfully completed.
Result:
SQL> SELECT *
2 FROM employee
3 ORDER BY deptno, empno;
DEPTNO EMPNO ENAME SALARY
---------- ---------- ---------- ----------
10 1 ZMO4RFN 830
10 2 AEXL34I 589
10 3 SI6X38Z 191
10 4 59EWI42 397
20 5 DBAMQDA 559
20 6 79X78JV 491
30 7 56ITU5V 178
30 8 09KPAIS 297
30 9 VQUVWDP 446
40 10 AHJZNVJ 182
40 11 0XWI3GC 553
40 12 7GNTCG4 629
40 13 23G871Z 480
13 rows selected.
SQL>
Adapting my answer to this question:
INSERT INTO employees (id, first_name, last_name, department_id)
SELECT employees__id__seq.NEXTVAL,
CASE FLOOR(DBMS_RANDOM.VALUE(1,6))
WHEN 1 THEN 'Faith'
WHEN 2 THEN 'Tom'
WHEN 3 THEN 'Anna'
WHEN 4 THEN 'Lisa'
WHEN 5 THEN 'Andy'
END,
CASE FLOOR(DBMS_RANDOM.VALUE(1,6))
WHEN 1 THEN 'Andrews'
WHEN 2 THEN 'Thorton'
WHEN 3 THEN 'Smith'
WHEN 4 THEN 'Jones'
WHEN 5 THEN 'Beirs'
END,
d.id
FROM ( SELECT id,
FLOOR(DBMS_RANDOM.VALUE(50,251)) AS num_employees
FROM departments
ORDER BY ROWNUM -- Materialize the sub-query so the random values are individually
-- generated.
) d
CROSS JOIN LATERAL (
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= d.num_employees
);
fiddle

SL No generation

There is a master table name as projects master
In another form if I select project-1 sl no need to generate from project master(21819001). after successful 1 record save, if I select same project-1
sl no need to generate like 21819002, for next 21819003, so on.
Again after 3 record save if I select projects-3 sl should generate like 41819001 so on.
I am using Oracle Forms 10g.
Here's an example of what you might do - create additional table which contains the most recent SL_NO for each project. That number is created with an autonomous transaction function which makes sure that in a multi-user environment you won't get duplicates.
PROJECTS_MASTER table and some sample data:
SQL> create table projects_master
2 (project number primary key);
Table created.
SQL> insert into projects_master
2 select 21819001 from dual union all
3 select 41819001 from dual;
2 rows created.
This table will contain the most recent SL_NO for each project
SQL> create table projects_sl_no
2 (project number constraint fk_prsl references projects_master (project),
3 sl_no number);
Table created.
The function itself; if row for PAR_PROJECT exists, it'll update it. Otherwise, it'll create a brand new row in PROJECTS_SL_NO table.
SQL> create or replace function f_proj_sl_no
2 (par_project in projects_master.project%type)
3 return projects_sl_no.sl_no%type
4 is
5 pragma autonomous_transaction;
6 l_sl_no projects_sl_no.sl_no%type;
7 begin
8 select b.sl_no + 1
9 into l_sl_no
10 from projects_sl_no b
11 where b.project = par_project
12 for update of b.sl_no;
13
14 update projects_sl_no b
15 set b.sl_no = l_sl_no
16 where b.project = par_project;
17
18 commit;
19 return (l_sl_no);
20 exception
21 when no_data_found
22 then
23 lock table projects_sl_no in exclusive mode;
24
25 insert into projects_sl_no (project, sl_no)
26 values (par_project, par_project);
27
28 commit;
29 return (par_project);
30 end f_proj_sl_no;
31 /
Function created.
Testing:
SQL> select f_proj_sl_no(21819001) sl_no from dual;
SL_NO
----------
21819001
SQL> select f_proj_sl_no(21819001) sl_no from dual;
SL_NO
----------
21819002
SQL> select f_proj_sl_no(21819001) sl_no from dual;
SL_NO
----------
21819003
SQL> select f_proj_sl_no(41819001) sl_no from dual;
SL_NO
----------
41819001
SQL> select * from projects_sl_no;
PROJECT SL_NO
---------- ----------
21819001 21819003
41819001 41819001
SQL>
As you use Forms, you could call the F_PROJ_SL_NO function in WHEN-VALIDATE-RECORD trigger, PRE-INSERT, or even create a before insert database trigger if you're inserting into a more complex table than the ones I created for testing purposes. Anyway, that should be a simpler part of the story.

How to INSERT data using CREATE VIEW object with multiple tables using INSTEAD OF trigger in Oracle?

Based on feedback from an stackoverflow user I researched docs.oracle.com about INSTEAD OF tirggers, but I still can't get this right. The view creates fine, but the INSTEAD OF trigger doesn't. Moreover, I don't understand how to set 'n' for multiple inputs. After I execute the code there is no indication of any error or if it worked. I loose the SQL> prompt and can't do anything, ending up having to restart the environment.
Here is what I came up with based off the example from Oracle:
SQL> CREATE OR REPLACE VIEW cust_order AS
2 SELECT book_customer.customerid, lastname, state, book_order.orderid, orderdate
3 FROM book_customer
4 JOIN book_order ON book_order.customerid = book_customer.customerid
5 ;
View created.
SQL>
SQL>
SQL> CREATE OR REPLACE TRIGGER cust_order_insert
2 INSTEAD OF INSERT ON cust_order
3 REFERENCING NEW AS n
4 FOR EACH ROW
5
6 DECLARE
7 rowcnt number;
8
9 BEGIN
10 SELECT COUNT(*) INTO rowcnt
11 FROM book_customer
12 WHERE book_customer.customerid = :n.book_customer.customerid;
13 IF rowcnt = 0 THEN
14 INSERT INTO book_customer(customerid, lastname, state)
15 VALUES (:n.book_customer.customerid, :n.lastname, :n.state);
16 ELSE
17 UPDATE book_customer SET book_customer.customerid = :n.customerid
18 WHERE book_customer.customerid = :n.customerid;
19 END IF;
20
21 SELECT COUNT(*) INTO rowcnt
22 FROM book_order
23 WHERE book_order.orderid = :n.orderid;
24 IF rowcnt = 0 THEN
25 INSERT INTO book_order(orderid, orderdate)
26 VALUES (:n.book_order.orderid, :n.orderdate);
27 ELSE
28 UPDATE book_order SET book_order.orderid = :n.orderid
29 WHERE book_order.orderdate = :n.orderdate;
30 END IF;
31 END;
32
33
34
35
36 --SQL> prompt won't come back.
37
38
39
40
Here are the table descriptions:
SQL> desc cust_order;
Name Null? Type
----------------------------------------------------------------- -------- ------------------------
CUSTOMERID NOT NULL NUMBER(4)
LASTNAME VARCHAR2(10)
STATE VARCHAR2(2)
ORDERID NOT NULL NUMBER(4)
ORDERDATE DATE
Definitions:
Create table Book_customer
(CustomerID NUMBER(4) CONSTRAINT PK_BOOKCUSTOMER PRIMARY KEY,
LastName VARCHAR2(10),
FirstName VARCHAR2(10),
Address VARCHAR2(20),
City VARCHAR2(20),
State VARCHAR2(2),
Zip VARCHAR2(5),
Referred NUMBER(4));
Create Table Book_order
(OrderID NUMBER(4) CONSTRAINT PK_BOOKORDER_ORDERID PRIMARY KEY,
CustomerID NUMBER(4) CONSTRAINT FK_BookOrder_BookCustomer REFERENCES Book_Customer (CustomerID),
OrderDate DATE,
ShipDate DATE,
ShipStreet VARCHAR2(20),
ShipCity VARCHAR2(20),
ShipState VARCHAR2(2),
ShipZip VARCHAR2(5));
Any ideas or constructive criticism is appreciated.
I wouldn't rely on 3rd party books as it's all described in the Oracle docs: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#i1025919 and http://docs.oracle.com/cd/B28359_01/server.111/b28310/views001.htm#ADMIN11782
Pay close attention to what Key-Preserved Tables mean. In your case, assuming that Book_Customer.Customer is a primary/unique key, you should be able to insert into Book_Customer, but not Cust_Order
I guess u have not ended the PL/SQL block properly. Just use a '/' at the end. And you can also include DML on both tables under same IF-ELSE block.
SQL> CREATE OR REPLACE TRIGGER cust_order_insert
2 INSTEAD OF INSERT ON cust_order
3 REFERENCING NEW AS n
4 FOR EACH ROW
5
6 DECLARE
7 rowcnt number;
8
9 BEGIN
10 SELECT COUNT(*) INTO rowcnt
11 FROM book_customer
12 WHERE book_customer.customerid = :n.book_customer.customerid;
13 IF rowcnt = 0 THEN
14 INSERT INTO book_customer(customerid, lastname, state)
15 VALUES (:n.book_customer.customerid, :n.lastname, :n.state);
16 INSERT INTO book_order(orderid, orderdate)
17 VALUES (:n.book_order.orderid, :n.orderdate);
18 ELSE
19 UPDATE book_customer SET book_customer.customerid = :n.customerid
20 WHERE book_customer.customerid = :n.customerid;
21 UPDATE book_order SET book_order.orderid = :n.orderid
22 WHERE book_order.orderdate = :n.orderdate;
23 END IF;
24 END;
25 /

procedure taking too much time to update the database

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;
is taking more than 15 minutes to update the database.
now i am updating this by using the following query in SQL PLUS:
EXECUTE UPDATE_CRDT_JV;
pls help me if any body knows the solution for this problem
I agree with the already given advice to start figuring out where your code is spending time. However, your case is quite common and I think I recognize this situation: you have coded your update statements in such a way that the other tables are accessed for every row of GL_DISTRIBUTION of that type.
The solution is to rewrite your update statements and I see two possibilities to do that efficiently:
1) Update a select statement (UPDATE (SELECT ...) SET ... WHERE ...). This requires some unique key constraints to be in place or using the BYPASS_UJVC hint.
2) Use a MERGE statement.
Below you see an example of how to rewrite your code using a single merge statement. I'm expecting big performance gains because the access of the other tables is now done once using a single outer join for each of the tables, instead of for every row in the GL_DISTRIBUTION table.
The example. Test data:
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>
Your procedure (for comparison):
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>
My suggestion:
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>
Let's run your procedure:
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>
My procedure returns the same results:
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.
Hope this helps.
Regards,
Rob.
The solution for this problem is:
Figure out where your code is
spending its time (i.e. profile it)
Figure out how to speed up the
slowest part
Repeat until performance is acceptable
If you prefer guesswork, then you might want to try any of the following:
Combine multiple UPDATEs into a single UPDATE statement, e.g. using a CASE condition as shown by #Aklopper.
Use MERGE instead of UPDATE to avoid correlated subqueries. Might be better, might not.
Look into the UPDATE_INV_DET procedure which is called at the end of the procedure shown.
I come from a SQL Server environment, won't a CASE UPDATE statement like this also help you(example of usage of the UPDATE CASE statement in SQL(don't know if Oracle has an equivalent methods) :
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

Resources