Handling exception in BULK COLLECT
Hi Experts,
For the following procedure if
I send the existed employee number of emp table as input
the procedure is executing successfully.
But if I send the employee number as input which does not exist in the emp table
the exection block does not handling the exception.
I am geeting the following error.
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "RAKULA.SP_TEST_EXCEPTION_BULK", line 8
ORA-06512: at line 7If I use WHEN OTHERS exception then I am able to handle that exception.
Why it's happening like this.
Please explain me.
CREATE OR REPLACE PROCEDURE RAKULA.sp_test_exception_bulk(i_empno NUMBER)
IS
t type_test1;
BEGIN
SELECT deptno BULK COLLECT INTO t
FROM emp
WHERE empno=i_empno;
FOR indx IN t.FIRST..t.LAST
loop
dbms_output.put_line(t(indx));
end loop;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('employee number' ||i_empno|| 'does not exist');
END sp_test_exception_bulk;
/Please help me how to handle that exception.
If I create the procedure without using
BULK COLLECT then I am able to handle that exception using WHEN NO_DATA_FOUND
In the following procedure I am able to handle the exception.
CREATE OR REPLACE PROCEDURE RAKULA.sp_test_exception(i_empno NUMBER,v_dept_no OUT NUMBER)
IS
BEGIN
SELECT deptno INTO v_dept_no FROM emp
WHERE empno=i_empno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('employee number' ||i_empno|| 'does not exist');
END sp_test_exception;
/
user9077483 wrote:
Hi Experts,
For the following procedure if
I send the existed employee number of emp table as input
the procedure is executing successfully.
But if I send the employee number as input which does not exist in the emp table
the exection block does not handling the exception.
I am geeting the following error.
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "RAKULA.SP_TEST_EXCEPTION_BULK", line 8
ORA-06512: at line 7If I use WHEN OTHERS exception then I am able to handle that exception.
Why it's happening like this.
Please explain me.
CREATE OR REPLACE PROCEDURE RAKULA.sp_test_exception_bulk(i_empno NUMBER)
IS
t type_test1;
BEGIN
SELECT deptno BULK COLLECT INTO t
FROM emp
WHERE empno=i_empno;
FOR indx IN t.FIRST..t.LAST
loop
dbms_output.put_line(t(indx));
end loop;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('employee number' ||i_empno|| 'does not exist');
END sp_test_exception_bulk;
/Please help me how to handle that exception.
If I create the procedure without using
BULK COLLECT then I am able to handle that exception using WHEN NO_DATA_FOUND
In the following procedure I am able to handle the exception.
CREATE OR REPLACE PROCEDURE RAKULA.sp_test_exception(i_empno NUMBER,v_dept_no OUT NUMBER)
IS
BEGIN
SELECT deptno INTO v_dept_no FROM emp
WHERE empno=i_empno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('employee number' ||i_empno|| 'does not exist');
END sp_test_exception;
The reason your Previous procedure does not execute completely is because you have handled only NO_DATA_FOUND exception, but the system generated
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "RAKULA.SP_TEST_EXCEPTION_BULK", line 8
ORA-06512: at line 7You will have to handle VALUE_ERROR exception in addition to NO_DATA_FOUND.
If you could tell us the Type of Collection "t", it would be helpful. What is the datatype of Dept column and the collection "t"?
Read this for PL/SQL predefined Exceptions.
Similar Messages
-
How can i handle exceptions in bulck collect?
Hi All,
in case of any exception will raise i just print the emp_no prefix with sqlerrm.but i got sqlerrm only ,now the emp_no is blank.how can i print my emp_no.
SET serveroutput ON;
DECLARE
TYPE employee_tab IS TABLE OF emp_ins%ROWTYPE
INDEX BY BINARY_INTEGER;
CURSOR c1 IS SELECT * FROM emp_ins ORDER BY emp_no;
Employee_data employee_tab;
lv_n_emp_no NUMBER;
lv_n_count NUMBER:=1;
BEGIN
IF c1%isopen THEN
CLOSE C1;
END IF;
OPEN C1;
FETCH C1 BULK COLLECT INTO Employee_data;
CLOSE C1;
FORALL i IN Employee_data.FIRST..Employee_data.LAST
INSERT INTO emp_test VALUES Employee_data(i);
lv_n_emp_no:=Employee_data(lv_n_count).emp_no;
lv_n_count:= NVL (lv_n_count, 1) + 1;
COMMIT;
Employee_data.DELETE;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(lv_n_emp_no||','||SQLERRM);
END;
Regards
Gopinath MSQL> create table emp_test as select * from emp where 1=2
2 /
Tabel is aangemaakt.
SQL> alter table emp_test add constraint emp_ck check (sal > 1500)
2 /
Tabel is gewijzigd.
SQL> declare
2 type t_employee_tab is table of emp%rowtype index by binary_integer;
3 r_employee_data t_employee_tab;
4 e_bulk_errors exception;
5 pragma exception_init ( e_bulk_errors, -24381 );
6 begin
7 select *
8 bulk collect into r_employee_data
9 from emp
10 order by empno
11 ;
12 forall i in r_employee_data.first..r_employee_data.last save exceptions
13 insert into emp_test values r_employee_data(i);
14 exception
15 when e_bulk_errors then
16 for j in 1..sql%bulk_exceptions.count
17 loop
18 dbms_output.put_line
19 ( r_employee_data(sql%bulk_exceptions(j).error_index).empno
20 || ', ' || r_employee_data(sql%bulk_exceptions(j).error_index).ename
21 || ', (sal=' || r_employee_data(sql%bulk_exceptions(j).error_index).sal
22 || ') :' || sqlerrm(-sql%bulk_exceptions(j).error_code)
23 );
24 end loop;
25 end;
26 /
7369, SMITH, (sal=800) :ORA-02290: check constraint (.) violated
7521, WARD, (sal=1250) :ORA-02290: check constraint (.) violated
7654, MARTIN, (sal=1250) :ORA-02290: check constraint (.) violated
7844, TURNER, (sal=1500) :ORA-02290: check constraint (.) violated
7876, ADAMS, (sal=1100) :ORA-02290: check constraint (.) violated
7900, JAMES, (sal=950) :ORA-02290: check constraint (.) violated
7934, MILLER, (sal=1300) :ORA-02290: check constraint (.) violated
PL/SQL-procedure is geslaagd.
SQL> select * from emp_test
2 /
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7499 ALLEN SALESMAN 7698 20-02-1981 00:00:00 1600 300 30
7566 JONES MANAGER 7839 02-04-1981 00:00:00 2975 20
7698 BLAKE MANAGER 7839 01-05-1981 00:00:00 2850 30
7782 CLARK MANAGER 7839 09-06-1981 00:00:00 2450 10
7788 SCOTT ANALYST 7566 09-12-1982 00:00:00 3000 20
7839 KING PRESIDENT 17-11-1981 00:00:00 5000 10
7902 FORD ANALYST 7566 03-12-1981 00:00:00 3000 20
7 rijen zijn geselecteerd.Regards,
Rob. -
Exceptional handling using Bulk Collect FORALL
Hi Members,
Following are by DB details
SELECT * FROM v$version;
Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production
PL/SQL Release 9.2.0.7.0 - Production
CORE 9.2.0.7.0 Production
TNS for HPUX: Version 9.2.0.7.0 - Production
NLSRTL Version 9.2.0.7.0 - ProductionI need to handle exception during Bulk Collect FORALL operation and update the table column with Status_flag as 'E' for given item name and extension id. Below is the code snippet for the same.
declare
k NUMBER;
cursor c_list_price
IS
SELECT /*+ leading(a) */ item_name,
'PUBLISH_TO_PRICE_CATALOG' ATTRIBUTE_NAME,
MAX(DECODE (attribute_name,
'PUBLISH_TO_PRICE_CATALOG',
attribute_value))
ATTRIBUTE_VALUE,
NULL GEOGRAPHY_LEVEL,
NULL GEOGRAPHY_VALUE,
NULL INCLUDE_GEOGRAPHY,
NULL EFFECTIVE_START_DATE,
NULL EFFECTIVE_TO_DATE,
EXTENSION_ID,
NULL PRICING_UNIT,
NULL ATTRIBUTE_FROM,
NULL ATTRIBUTE_TO,
NULL FIXED_BASE_PRICE,
NULL PARENT_ATTRIBUTE,
NULL DURATION_QUANTITY,
NULL ATTRIBUTE2,
NULL ATTRIBUTE3,
NULL ATTRIBUTE4,
NULL ATTRIBUTE5,
NULL ATTRIBUTE6,
NULL ATTRIBUTE7,
NULL ATTRIBUTE8,
NULL ATTRIBUTE9,
NULL ATTRIBUTE10,
NULL ATTRIBUTE11,
NULL ATTRIBUTE12,
NULL ATTRIBUTE13,
NULL ATTRIBUTE14,
NULL ATTRIBUTE15,
--ORG_CODE,
ITEM_CATALOG_CATEGORY ITEM_CATEGORY,
a.INVENTORY_ITEM_ID INVENTORY_ITEM_ID
FROM XXCPD_ITM_SEC_UDA_DETAILS_TB a
WHERE DECODE(attribute_group_name,'LIST_PRICE',DECODE(STATUS_FLAG,'E',1,'P',2,3)
,'XXITM_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',4,'P',5,6)
,'XXITM_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',4,'P',5,6)
,'XXITM_ADV_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',7,'P',8,9)
,'XXITM_ADV_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',7,'P',8,9)
,'XXITM_ADV_FORM_PRICING_HWSW',DECODE(STATUS_FLAG,'E',10,'P',11,12)
,'XXITM_ADV_FORM_PRICING_SWSUB',DECODE(STATUS_FLAG,'E',10,'P',11,12)
,'XXITM_ROUTE_TO_MARKET',DECODE(STATUS_FLAG,'E',13,'P',14,15)) in (1,2,3)
AND exists(select /*+ no_merge */ '1' from mtl_system_items_b b where a.inventory_item_id=b.inventory_item_id and b.organization_id=1)
GROUP BY item_name,
extension_id,
ITEM_CATALOG_CATEGORY,
INVENTORY_ITEM_ID;
TYPE myarray IS TABLE OF c_list_price%ROWTYPE;
c_lp myarray;
BEGIN
OPEN c_list_price;
LOOP
FETCH c_list_price BULK COLLECT INTO c_lp
LIMIT 50000;
IF c_lp.count = 0 THEN
EXIT;
END IF;
Begin
FORALL i IN c_lp.FIRST..c_lp.LAST SAVE EXCEPTIONS
INSERT /*+append*/ INTO XXCPD_ITEM_PRICING_ATTR_BKP2(
line_id,
ITEM_NAME,
ATTRIBUTE_NAME,
ATTRIBUTE_VALUE,
GEOGRAPHY_LEVEL,
GEOGRAPHY_VALUE,
INCLUDE_GEOGRAPHY,
EFFECTIVE_START_DATE,
EFFECTIVE_TO_DATE,
EXTENSION_ID,
PRICING_UNIT,
ATTRIBUTE_FROM,
ATTRIBUTE_TO,
FIXED_BASE_PRICE,
PARENT_ATTRIBUTE,
DURATION_QUANTITY,
ATTRIBUTE2,
ATTRIBUTE3,
ATTRIBUTE4,
ATTRIBUTE5,
ATTRIBUTE6,
ATTRIBUTE7,
ATTRIBUTE8,
ATTRIBUTE9,
ATTRIBUTE10,
ATTRIBUTE11,
ATTRIBUTE12,
ATTRIBUTE13,
ATTRIBUTE14,
ATTRIBUTE15,
ITEM_CATEGORY,
INVENTORY_ITEM_ID
VALUES
xxcpd.xxcpd_if_prc_line_id_s.NEXTVAL
,c_lp(i).ITEM_NAME
,c_lp(i).ATTRIBUTE_NAME
,c_lp(i).ATTRIBUTE_VALUE
,c_lp(i).GEOGRAPHY_LEVEL
,c_lp(i).GEOGRAPHY_VALUE
,c_lp(i).INCLUDE_GEOGRAPHY
,c_lp(i).EFFECTIVE_START_DATE
,c_lp(i).EFFECTIVE_TO_DATE
,c_lp(i).EXTENSION_ID
,c_lp(i).PRICING_UNIT
,c_lp(i).ATTRIBUTE_FROM
,c_lp(i).ATTRIBUTE_TO
,c_lp(i).FIXED_BASE_PRICE
,c_lp(i).PARENT_ATTRIBUTE
,c_lp(i).DURATION_QUANTITY
,c_lp(i).ATTRIBUTE2
,c_lp(i).ATTRIBUTE3
,c_lp(i).ATTRIBUTE4
,c_lp(i).ATTRIBUTE5
,c_lp(i).ATTRIBUTE6
,c_lp(i).ATTRIBUTE7
,c_lp(i).ATTRIBUTE8
,c_lp(i).ATTRIBUTE9
,c_lp(i).ATTRIBUTE10
,c_lp(i).ATTRIBUTE11
,c_lp(i).ATTRIBUTE12
,c_lp(i).ATTRIBUTE13
,c_lp(i).ATTRIBUTE14
,c_lp(i).ATTRIBUTE15
,c_lp(i).ITEM_CATEGORY
,c_lp(i).INVENTORY_ITEM_ID
EXCEPTION
WHEN OTHERS THEN
FOR j IN 1..SQL%bulk_exceptions.Count
LOOP
UPDATE XXCPD_ITM_SEC_UDA_DETAILS_TB
SET status_flag = 'E',
last_updated_by = 1,
last_update_date = SYSDATE
WHERE item_name = c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).item_name
AND extension_id=c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).extension_id;
COMMIT;
IF c_list_price%ISOPEN THEN
CLOSE c_list_price;
END IF;
FND_FILE.put_line(FND_FILE.output,'********************Exception Occured*************:-- '||SYSTIMESTAMP);
END LOOP;
END;
END LOOP;
CLOSE c_list_price;
COMMIT;
end;and I am getting following error
ORA-06550: line 156, column 47:
PL/SQL: ORA-00911: invalid character
ORA-06550: line 152, column 21:
PL/SQL: SQL Statement ignoredpointing to following lines in exception block for update clause.
WHERE item_name = c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).item_name
AND extension_id=c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).extension_id; can some one please help me out with the issue.
Thanks in AdvanceHave re-written the code in the following manner
declare
lv_ITEM_NAME DBMS_SQL.VARCHAR2S;
lv_ITEM_CATEGORY DBMS_SQL.VARCHAR2S;
lv_INVENTORY_ITEM_ID DBMS_SQL.NUMBER_TABLE;
lv_ATTRIBUTE_NAME DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE_VALUE DBMS_SQL.VARCHAR2S;
lv_GEOGRAPHY_LEVEL DBMS_SQL.VARCHAR2S;
lv_GEOGRAPHY_VALUE DBMS_SQL.VARCHAR2S;
lv_INCLUDE_GEOGRAPHY DBMS_SQL.VARCHAR2S;
lv_EFFECTIVE_START_DATE DBMS_SQL.date_table;
lv_EFFECTIVE_TO_DATE DBMS_SQL.date_table;
lv_EXTENSION_ID DBMS_SQL.NUMBER_TABLE;
lv_PRICING_UNIT DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE_FROM DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE_TO DBMS_SQL.VARCHAR2S;
lv_FIXED_BASE_PRICE DBMS_SQL.NUMBER_TABLE;
lv_PARENT_ATTRIBUTE DBMS_SQL.VARCHAR2S;
lv_DURATION_QUANTITY DBMS_SQL.NUMBER_TABLE;
lv_ATTRIBUTE2 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE3 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE4 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE5 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE6 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE7 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE8 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE9 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE10 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE11 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE12 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE13 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE14 DBMS_SQL.VARCHAR2S;
lv_ATTRIBUTE15 DBMS_SQL.VARCHAR2S;
l_item_name XXCPD_ITM_SEC_UDA_DETAILS_TB.item_name%TYPE;
l_extension_id XXCPD_ITM_SEC_UDA_DETAILS_TB.extension_id%TYPE;
cursor c_list_price
IS
SELECT /*+ leading(a) */ item_name,
'PUBLISH_TO_PRICE_CATALOG' ATTRIBUTE_NAME,
MAX(DECODE (attribute_name,
'PUBLISH_TO_PRICE_CATALOG',
attribute_value))
ATTRIBUTE_VALUE,
NULL GEOGRAPHY_LEVEL,
NULL GEOGRAPHY_VALUE,
NULL INCLUDE_GEOGRAPHY,
NULL EFFECTIVE_START_DATE,
NULL EFFECTIVE_TO_DATE,
EXTENSION_ID,
NULL PRICING_UNIT,
NULL ATTRIBUTE_FROM,
NULL ATTRIBUTE_TO,
NULL FIXED_BASE_PRICE,
NULL PARENT_ATTRIBUTE,
NULL DURATION_QUANTITY,
NULL ATTRIBUTE2,
NULL ATTRIBUTE3,
NULL ATTRIBUTE4,
NULL ATTRIBUTE5,
NULL ATTRIBUTE6,
NULL ATTRIBUTE7,
NULL ATTRIBUTE8,
NULL ATTRIBUTE9,
NULL ATTRIBUTE10,
NULL ATTRIBUTE11,
NULL ATTRIBUTE12,
NULL ATTRIBUTE13,
NULL ATTRIBUTE14,
NULL ATTRIBUTE15,
--ORG_CODE,
ITEM_CATALOG_CATEGORY ITEM_CATEGORY,
a.INVENTORY_ITEM_ID INVENTORY_ITEM_ID
FROM XXCPD_ITM_SEC_UDA_DETAILS_TB a
WHERE DECODE(attribute_group_name,'LIST_PRICE',DECODE(STATUS_FLAG,'E',1,'P',2,3)
,'XXITM_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',4,'P',5,6)
,'XXITM_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',4,'P',5,6)
,'XXITM_ADV_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',7,'P',8,9)
,'XXITM_ADV_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',7,'P',8,9)
,'XXITM_ADV_FORM_PRICING_HWSW',DECODE(STATUS_FLAG,'E',10,'P',11,12)
,'XXITM_ADV_FORM_PRICING_SWSUB',DECODE(STATUS_FLAG,'E',10,'P',11,12)
,'XXITM_ROUTE_TO_MARKET',DECODE(STATUS_FLAG,'E',13,'P',14,15)) in (1,2,3)
AND exists(select /*+ no_merge */ '1' from mtl_system_items_b b where a.inventory_item_id=b.inventory_item_id and b.organization_id=1)
GROUP BY item_name,
extension_id,
ITEM_CATALOG_CATEGORY,
INVENTORY_ITEM_ID;
BEGIN
OPEN c_list_price;
LOOP
lv_ITEM_NAME.delete;
lv_ITEM_CATEGORY.delete;
lv_INVENTORY_ITEM_ID.delete;
lv_ATTRIBUTE_NAME.delete;
lv_ATTRIBUTE_VALUE.delete;
lv_GEOGRAPHY_LEVEL.delete;
lv_GEOGRAPHY_VALUE.delete;
lv_INCLUDE_GEOGRAPHY.delete;
lv_EFFECTIVE_START_DATE.delete;
lv_EFFECTIVE_TO_DATE.delete;
lv_EXTENSION_ID.delete;
lv_PRICING_UNIT.delete;
lv_ATTRIBUTE_FROM.delete;
lv_ATTRIBUTE_TO.delete;
lv_FIXED_BASE_PRICE.delete;
lv_PARENT_ATTRIBUTE.delete;
lv_DURATION_QUANTITY.delete;
lv_ATTRIBUTE2.delete;
lv_ATTRIBUTE3.delete;
lv_ATTRIBUTE4.delete;
lv_ATTRIBUTE5.delete;
lv_ATTRIBUTE6.delete;
lv_ATTRIBUTE7.delete;
lv_ATTRIBUTE8.delete;
lv_ATTRIBUTE9.delete;
lv_ATTRIBUTE10.delete;
lv_ATTRIBUTE11.delete;
lv_ATTRIBUTE12.delete;
lv_ATTRIBUTE13.delete;
lv_ATTRIBUTE14.delete;
lv_ATTRIBUTE15.delete;
FETCH c_list_price BULK COLLECT INTO lv_ITEM_NAME
,lv_ATTRIBUTE_NAME
,lv_ATTRIBUTE_VALUE
,lv_GEOGRAPHY_LEVEL
,lv_GEOGRAPHY_VALUE
,lv_INCLUDE_GEOGRAPHY
,lv_EFFECTIVE_START_DATE
,lv_EFFECTIVE_TO_DATE
,lv_EXTENSION_ID
,lv_PRICING_UNIT
,lv_ATTRIBUTE_FROM
,lv_ATTRIBUTE_TO
,lv_FIXED_BASE_PRICE
,lv_PARENT_ATTRIBUTE
,lv_DURATION_QUANTITY
,lv_ATTRIBUTE2
,lv_ATTRIBUTE3
,lv_ATTRIBUTE4
,lv_ATTRIBUTE5
,lv_ATTRIBUTE6
,lv_ATTRIBUTE7
,lv_ATTRIBUTE8
,lv_ATTRIBUTE9
,lv_ATTRIBUTE10
,lv_ATTRIBUTE11
,lv_ATTRIBUTE12
,lv_ATTRIBUTE13
,lv_ATTRIBUTE14
,lv_ATTRIBUTE15
,lv_ITEM_CATEGORY
,lv_INVENTORY_ITEM_ID
LIMIT 50000;
IF lv_INVENTORY_ITEM_ID.count = 0 THEN
EXIT;
END IF;
Begin
FORALL I IN 1..lv_INVENTORY_ITEM_ID.count SAVE EXCEPTIONS
INSERT /*+append*/ INTO XXCPD_ITEM_PRICING_ATTR_BKP2(
line_id,
ITEM_NAME,
ATTRIBUTE_NAME,
ATTRIBUTE_VALUE,
GEOGRAPHY_LEVEL,
GEOGRAPHY_VALUE,
INCLUDE_GEOGRAPHY,
EFFECTIVE_START_DATE,
EFFECTIVE_TO_DATE,
EXTENSION_ID,
PRICING_UNIT,
ATTRIBUTE_FROM,
ATTRIBUTE_TO,
FIXED_BASE_PRICE,
PARENT_ATTRIBUTE,
DURATION_QUANTITY,
ATTRIBUTE2,
ATTRIBUTE3,
ATTRIBUTE4,
ATTRIBUTE5,
ATTRIBUTE6,
ATTRIBUTE7,
ATTRIBUTE8,
ATTRIBUTE9,
ATTRIBUTE10,
ATTRIBUTE11,
ATTRIBUTE12,
ATTRIBUTE13,
ATTRIBUTE14,
ATTRIBUTE15,
ITEM_CATEGORY,
INVENTORY_ITEM_ID
VALUES
xxcpd.xxcpd_if_prc_line_id_s.NEXTVAL
,lv_ITEM_NAME(i)
,lv_ATTRIBUTE_NAME(i)
,lv_ATTRIBUTE_VALUE(i)
,lv_GEOGRAPHY_LEVEL(i)
,lv_GEOGRAPHY_VALUE(i)
,lv_INCLUDE_GEOGRAPHY(i)
,lv_EFFECTIVE_START_DATE(i)
,lv_EFFECTIVE_TO_DATE(i)
,lv_EXTENSION_ID(i)
,lv_PRICING_UNIT(i)
,lv_ATTRIBUTE_FROM(i)
,lv_ATTRIBUTE_TO(i)
,lv_FIXED_BASE_PRICE(i)
,lv_PARENT_ATTRIBUTE(i)
,lv_DURATION_QUANTITY(i)
,lv_ATTRIBUTE2(i)
,lv_ATTRIBUTE3(i)
,lv_ATTRIBUTE4(i)
,lv_ATTRIBUTE5(i)
,lv_ATTRIBUTE6(i)
,lv_ATTRIBUTE7(i)
,lv_ATTRIBUTE8(i)
,lv_ATTRIBUTE9(i)
,lv_ATTRIBUTE10(i)
,lv_ATTRIBUTE11(i)
,lv_ATTRIBUTE12(i)
,lv_ATTRIBUTE13(i)
,lv_ATTRIBUTE14(i)
,lv_ATTRIBUTE15(i)
,lv_ITEM_CATEGORY(i)
,lv_INVENTORY_ITEM_ID(i)
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
FOR j IN 1..SQL%bulk_exceptions.Count
LOOP
l_item_name:=lv_ITEM_NAME(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX);
l_extension_id:=lv_EXTENSION_ID(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX);
UPDATE XXCPD_ITM_SEC_UDA_DETAILS_TB
SET status_flag = 'E',
last_updated_by = 1,
last_update_date = SYSDATE
WHERE item_name = l_item_name
AND extension_id=l_extension_id;
COMMIT;
FND_FILE.put_line(FND_FILE.output,'********************Exception Occured*************:-- '||SYSTIMESTAMP);
END LOOP;
END;
END LOOP;
CLOSE c_list_price;
COMMIT;
end; -
SAVE EXCEPTIONS when fetching from cursors by BULK COLLECT possible?
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
Hello,
I'm using an Cursor's FETCH by BULK COLLECT INTO mydata...
Is it possible to SAVE EXCEPTIONS like with FORALL? Or is there any other possibility to handle exceptions during bulk-fetches?
Regards,
MartinThe cursor's SELECT-statement uses TO_DATE(juldat,'J')-function (for converting an julian date value to DATE), but some rows contain an invalid juldat-value (leading to ORA-01854).
I want to handle this "rows' exceptions" like in FORALL.
But it could also be any other (non-Oracle/self-made) function within "any" BULK instruction raising (un)wanted exceptions... how can I handle these ones?
Martin -
Why bulk collect ,bulk update are faster?
Hi all gurus,
I have one doubt ,all of us knows that bulk collect is faster but i want to know why it is faster? what is mechanism behind that?
what oracle does internally so that it works faster?
thanks in advance
vijay
Edited by: vijay29 on Mar 2, 2009 2:24 AMExample for Bulk Collect.
DECLARE
TYPE myvar2 IS TABLE OF a%ROWTYPE; -- Creating a Pl/SQL table
CURSOR c1
IS
SELECT *
FROM a; -- Declaring a cursor
myvar1 myvar2; -- Declaring a PL/SQL Table variable.
BEGIN
OPEN c1;
Here is a finding when using 'LIMIT' clause in 'BULK COLLECT' statement.
Example :
Note : Table EMP has 15 records.
CASE #1:
SQL> SELECT COUNT (*)
FROM emp;
COUNT(*)
15
DECLARE
TYPE numtab IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
CURSOR c1
IS
SELECT empno
FROM emp;
empnos numtab;
ROWS NATURAL := 10;
BEGIN
OPEN c1;
LOOP
/* The following statement fetches 10 rows (or less). */
FETCH c1
BULK COLLECT INTO empnos LIMIT ROWS;
EXIT WHEN c1%NOTFOUND;
FORALL i IN empnos.FIRST .. empnos.LAST
DELETE FROM emp
WHERE empno = empnos (i);
END LOOP;
CLOSE c1;
END;
Observation : When the above code segment is run the total records deleted will be only 10 as shown below.
SQL> SELECT COUNT (*)
FROM emp;
COUNT(*)
5
Since the statement 'EXIT WHEN c1%NOTFOUND' executes before the DML statement (DELETE in this case),
the loop terminates as soon as the cursor (C1) has the rowcount(5 rows) less than the LIMIT count(10 rows).
CASE #2:
SQL> SELECT COUNT (*)
FROM emp;
COUNT(*)
15
DECLARE
TYPE numtab IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
CURSOR c1
IS
SELECT empno
FROM emp;
empnos numtab;
ROWS NATURAL := 10;
BEGIN
OPEN c1;
LOOP
/* The following statement fetches 10 rows (or less). */
FETCH c1
BULK COLLECT INTO empnos LIMIT ROWS;
FORALL i IN empnos.FIRST .. empnos.LAST
DELETE FROM emp
WHERE empno = empnos (i);
EXIT WHEN c1%NOTFOUND;
END LOOP;
CLOSE c1;
END;
Observation : When the above code segment is run the total records deleted will be 15 as shown below.
SQL> SELECT COUNT (*)
FROM emp;
COUNT(*)
0
Since the statement 'EXIT WHEN c1%NOTFOUND' executes after the DML statement (DELETE in this case),
the loop terminates after executing the DML & deletes the rest of the 5 records also and exits.
Conclusion :
When handling 'LIMIT' with 'BULK COLLECT INTO' statements, better to use the statement
'EXIT WHEN <cursorname>%NOTFOUND' after the DML statement.
And also use the following way with set of statements:
Declare
Type Numtab Is Table Of Number
Index By Binary_Integer;
Cursor C1
Is
Select Empno
From Emp;
Empnos Numtab;
Rows Natural := 10;
Tot_Recs Number;
Begin
Open C1;
Loop
/* The Following Statement Fetches 10 Rows (Or Less). */
Fetch C1
Bulk Collect Into Empnos Limit Rows;
If Msagrmnt%rowcount > Tot_Recs
Then
For I In Empnos.First .. Empnos.Last
Loop
-- Here We Can Include Set Of Pl/sql Stmts And We May Store Other Values Into
-- Pl/sql Table And Then Insert Into The Table (For Both Cursor Selection Values And Other Selection Values As Below)
End Loop;
Forall I In Empnos.First..Empnos.Last
Insert Into Empno1 Values … Ie Pl/sql Table Variables;
End If;
Tot_Recs := C1%rowcount;
Exit When C1%notfound;
End Loop;
Close C1;
End; -
How to handle multiple save exceptions (Bulk Collect)
Hi
How to handle Multiple Save exceptions? Is it possible to rollback to first deletion(of child table) took place in the procedure.
There are 3 tables
txn_header_interface(Grand Parent)
orders(parent)
order_items (Child)
One transaction can have one or multiple orders in it.
and one orders can have one or multiple order_items in it.
We need to delete the data from child table first then its parent and then from the grand parent table.if some error occurs anywhere I need to rollback to child record deletion. Since there is flag in child table which tells us when to delete data from database.
Is it possible to give name to Save exceptions?
e.g.
FORALL i IN ABC.FIRST..ABC.LAST SAVE EXCEPTIONS A
FORALL i IN abc.FIRST..ABC.LAST SAVE EXCEPTIONS B
if some error occurs then
ROLLBACK A; OR ROLLBACK B;
Please find the procedure attached
How to handle the errors with Save exception and rollback upto child table deletion.
CREATE OR REPLACE
PROCEDURE DELETE_CONFIRMED_DATA IS
TYPE TXN_HDR_INFC_ID IS TABLE OF TXN_HEADER_INTERFACE.ID%TYPE;
TXN_HDR_INFC_ID_ARRAY TXN_HDR_INFC_ID;
ERROR_COUNT NUMBER;
BULK_ERRORS EXCEPTION;
PRAGMA exception_init(bulk_errors, -24381);
BEGIN
SELECT THI.ID BULK COLLECT
INTO TXN_HDR_INFC_ID_ARRAY
FROM TXN_HEADER_INTERFACE THI,ORDERS OS,ORDER_ITEMS OI
WHERE THI.ID = OS.TXN_HDR_INFC_ID
AND OS.ID = OI.ORDERS_ID
AND OI.POSTING_ITEM_ID = VPI.ID
OI.DW_STATUS_FLAG =4 --data is moved to Datawarehouse
MINUS
(SELECT THI.ID FROM TXN_HEADER_INTERFACE THI,ORDERS OS,ORDER_ITEMS OI
WHERE THI.ID = OS.TXN_HDR_INFC_ID
AND OS.ID = OI.ORDERS_ID
OI.DW_STATUS_FLAG !=4);
IF SQL%NOTFOUND
THEN
EXIT;
END IF;
FORALL i IN TXN_HDR_INFC_ID_ARRAY.FIRST..TXN_HDR_INFC_ID_ARRAY.LAST SAVE
EXCEPTIONS
DELETE FROM ORDER_ITEMS OI
WHERE OI.ID IN (SELECT OI.ID FROM ORDER_ITEMS OI,ORDERS
OS,TXN_HEADER_INTERFACE THI
WHERE OS.ID = OI.ORDERS_ID
AND OS.TXN_HDR_INFC_ID = THI.ID
AND THI.ID = TXN_HDR_INFC_ID_ARRAY(i));
FORALL i IN TXN_HDR_INFC_ID_ARRAY.FIRST..TXN_HDR_INFC_ID_ARRAY.LAST SAVE
EXCEPTIONS
DELETE FROM ORDERS OS
WHERE OS.ID IN (SELECT OS.ID FROM ORDERS OS,TXN_HEADER_INTERFACE THI
WHERE OS.TXN_HDR_INFC_ID = THI.ID
AND THI.ID = TXN_HDR_INFC_ID_ARRAY(i));
FORALL i IN TXN_HDR_INFC_ID_ARRAY.FIRST..TXN_HDR_INFC_ID_ARRAY.LAST SAVE
EXCEPTIONS
DELETE FROM TXN_HEADER_INTERFACE THI
WHERE THI.ID = TXN_HDR_INFC_ID_ARRAY(i);
COMMIT;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSDATE, 'DD-MON-YY HH:MIPM')||':
DELETE_CONFIRMED_DATA: INFO:DELETION SUCCESSFUL');
EXCEPTION
WHEN OTHERS THEN
ERROR_COUNT := SQL%BULK_EXCEPTIONS.COUNT;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSDATE, 'DD-MON-YY HH:MIPM')||':
DELETE_CONFIRMED_DATA: ERROR:Number of errors is ' ||ERROR_COUNT);
FOR indx IN 1..ERROR_COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Error ' || indx || 'occurred during
'||'iteration'||SQL%BULK_EXCEPTIONS(indx).ERROR_INDEX);
DBMS_OUTPUT.PUT_LINE('Error is '
||SQLERRM(-SQL%BULK_EXCEPTIONS(indx).ERROR_CODE));
END LOOP;
END DELETE_CONFIRMED_DATA;
Any suggestion would be of great help.
Thanks in advance
AnuIf you have one or two places in your code that need multiple exceptions, just do it with multiple catch statements. Unless you are trying to write the most compact Programming 101 homework program, inventing tricks to remove two lines of code is not good use of your time.
If you have multiple catches all over your code it could be a code smell. You may have too much stuff happening inside one try statement. It becomes hard to know what method call throws one of those exceptions, and you end up handling an exception from some else piece of code than what you intended. E.g. you mention NumberFormatException -- only process one user input inside that try/catch so it is easy to see what error message is given if that particular input is gunk. The next step of processing goes inside its own try/catch.
In my case, the ArrayIndexOutOfBoundsException and
NumberFormatException should be handled by the same way.Why?
I don't think I have ever seen an ArrayIndexOutOfBoundsException that didn't indicate a bug in the code. Instead of an AIOOBE perhaps there should be an if statement somewhere that prevents it, or the algorithm logic should prevent it automatically. -
EXCEPTION HANDLE IN BULK COLLECT
HOW WILL I HANDLE EXCEPTION IN BULKCOLLECT
SUPPOSE IF NO DATA IS FOUND I WANT TO SET A VARIABLE IS 0 THEN THERE AFTER OTHER STAEMENT ARE PROCESSED
ELSE ALL STATEMENT ARE PROCESSED.when you use bulk collect with select into, it doesn't raise any exception when no data is found. you can simple COUNT the elements in your array structure (in which you have collected the data) to check whether any rows have been processed or not.
like...
1 DECLARE
2 TYPE tt IS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;
3 v_tt tt;
4 BEGIN
5 SELECT ename BULK COLLECT INTO v_tt FROM emp WHERE empno = 7899;
6 DBMS_OUTPUT.PUT_LINE(v_tt.COUNT);
7* END;
11:43:37 SQL> /
0
PL/SQL procedure successfully completed. -
How to handle the bad record while using bulk collect with limit.
Hi
How to handle the Bad record as part of the insertion/updation to avoid the transaction.
Example:
I am inserting into table with LIMIT of 1000 records and i've got error at 588th record.
i want to commit the transaction with 588 inserted record in table and log the error into
error logging table then i've to continue with transaction with 560th record.
Can anyone suggest me in this case.
Regards,
yuva>
How to handle the Bad record as part of the insertion/updation to avoid the transaction.
>
Use the SAVE EXCEPTIONS clause of the FORALL if you are doing bulk inserts.
See SAVE EXCEPTIONS in the PL/SQL Language doc
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/tuning.htm
And then see Example 12-9 Bulk Operation that continues despite exceptions
>
Example 12-9 Bulk Operation that Continues Despite Exceptions
-- Temporary table for this example:
CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE empid_tab IS TABLE OF employees.employee_id%TYPE;
emp_sr empid_tab;
-- Exception handler for ORA-24381:
errors NUMBER;
dml_errors EXCEPTION;
PRAGMA EXCEPTION_INIT(dml_errors, -24381);
BEGIN
SELECT employee_id
BULK COLLECT INTO emp_sr FROM emp_temp
WHERE hire_date < '30-DEC-94';
-- Add '_SR' to job_id of most senior employees:
FORALL i IN emp_sr.FIRST..emp_sr.LAST SAVE EXCEPTIONS
UPDATE emp_temp SET job_id = job_id || '_SR'
WHERE emp_sr(i) = emp_temp.employee_id;
-- If errors occurred during FORALL SAVE EXCEPTIONS,
-- a single exception is raised when the statement completes.
EXCEPTION
-- Figure out what failed and why
WHEN dml_errors THEN
errors := SQL%BULK_EXCEPTIONS.COUNT;
DBMS_OUTPUT.PUT_LINE
('Number of statements that failed: ' || errors);
FOR i IN 1..errors LOOP
DBMS_OUTPUT.PUT_LINE('Error #' || i || ' occurred during '||
'iteration #' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
DBMS_OUTPUT.PUT_LINE('Error message is ' ||
SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
DROP TABLE emp_temp; -
Hi all,
I have a performance issue in the below code,where i am trying to insert the data from table_stg into target_tab and in parent_tab tables and then to child tables via cursor with bulk collect .the target_tab and parent_tab are huge tables and have a row wise trigger enabled on it .the trigger is mandatory . This timetaken for this block to execute is 5000 seconds.Now my requirement is to reduce it to 5 to 10 mins.
can someone please guide me here.Its bit urgent .Awaiting for your response.
declare
vmax_Value NUMBER(5);
vcnt number(10);
id_val number(20);
pc_id number(15);
vtable_nm VARCHAR2(100);
vstep_no VARCHAR2(10);
vsql_code VARCHAR2(10);
vsql_errm varchar2(200);
vtarget_starttime timestamp;
limit_in number :=10000;
idx number(10);
cursor stg_cursor is
select
DESCRIPTION,
SORT_CODE,
ACCOUNT_NUMBER,
to_number(to_char(CORRESPONDENCE_DATE,'DD')) crr_day,
to_char(CORRESPONDENCE_DATE,'MONTH') crr_month,
to_number(substr(to_char(CORRESPONDENCE_DATE,'DD-MON-YYYY'),8,4)) crr_year,
PARTY_ID,
GUID,
PAPERLESS_REF_IND,
PRODUCT_TYPE,
PRODUCT_BRAND,
PRODUCT_HELD_ID,
NOTIFICATION_PREF,
UNREAD_CORRES_PERIOD,
EMAIL_ID,
MOBILE_NUMBER,
TITLE,
SURNAME,
POSTCODE,
EVENT_TYPE,
PRIORITY_IND,
SUBJECT,
EXT_PRD_ID_TX,
EXT_PRD_HLD_ID_TX,
EXT_SYS_ID,
EXT_PTY_ID_TX,
ACCOUNT_TYPE_CD,
COM_PFR_TYP_TX,
COM_PFR_OPT_TX,
COM_PFR_RSN_CD
from table_stg;
type rec_type is table of stg_rec_type index by pls_integer;
v_rt_all_cols rec_type;
BEGIN
vstep_no := '0';
vmax_value := 0;
vtarget_starttime := systimestamp;
id_val := 0;
pc_id := 0;
success_flag := 0;
vstep_no := '1';
vtable_nm := 'before cursor';
OPEN stg_cursor;
vstep_no := '2';
vtable_nm := 'After cursor';
LOOP
vstep_no := '3';
vtable_nm := 'before fetch';
--loop
FETCH stg_cursor BULK COLLECT INTO v_rt_all_cols LIMIT limit_in;
vstep_no := '4';
vtable_nm := 'after fetch';
--EXIT WHEN v_rt_all_cols.COUNT = 0;
EXIT WHEN stg_cursor%NOTFOUND;
FOR i IN 1 .. v_rt_all_cols.COUNT
LOOP
dbms_output.put_line(upper(v_rt_all_cols(i).event_type));
if (upper(v_rt_all_cols(i).event_type) = upper('System_enforced')) then
vstep_no := '4.1';
vtable_nm := 'before seq sel';
select PC_SEQ.nextval into pc_id from dual;
vstep_no := '4.2';
vtable_nm := 'before insert corres';
INSERT INTO target1_tab
(ID,
PARTY_ID,
PRODUCT_BRAND,
SORT_CODE,
ACCOUNT_NUMBER,
EXT_PRD_ID_TX,
EXT_PRD_HLD_ID_TX,
EXT_SYS_ID,
EXT_PTY_ID_TX,
ACCOUNT_TYPE_CD,
COM_PFR_TYP_TX,
COM_PFR_OPT_TX,
COM_PFR_RSN_CD,
status)
VALUES
(pc_id,
v_rt_all_cols(i).party_id,
decode(v_rt_all_cols(i).product_brand,'LTB',2,'HLX',1,'HAL',1,'BOS',3,'VER',4,0),
v_rt_all_cols(i).sort_code,
'XXXX'||substr(trim(v_rt_all_cols(i).ACCOUNT_NUMBER),length(trim(v_rt_all_cols(i).ACCOUNT_NUMBER))-3,4),
v_rt_all_cols(i).EXT_PRD_ID_TX,
v_rt_all_cols(i).EXT_PRD_HLD_ID_TX,
v_rt_all_cols(i).EXT_SYS_ID,
v_rt_all_cols(i).EXT_PTY_ID_TX,
v_rt_all_cols(i).ACCOUNT_TYPE_CD,
v_rt_all_cols(i).COM_PFR_TYP_TX,
v_rt_all_cols(i).COM_PFR_OPT_TX,
v_rt_all_cols(i).COM_PFR_RSN_CD,
NULL);
vstep_no := '4.3';
vtable_nm := 'after insert corres';
else
select COM_SEQ.nextval into id_val from dual;
vstep_no := '6';
vtable_nm := 'before insertcomm';
if (upper(v_rt_all_cols(i).event_type) = upper('REMINDER')) then
vstep_no := '6.01';
vtable_nm := 'after if insertcomm';
insert into parent_tab
(ID ,
CTEM_CODE,
CHA_CODE,
CT_CODE,
CONTACT_POINT_ID,
SOURCE,
RECEIVED_DATE,
SEND_DATE,
RETRY_COUNT)
values
(id_val,
lower(v_rt_all_cols(i).event_type),
decode(v_rt_all_cols(i).product_brand,'LTB',2,'HLX',1,'HAL',1,'BOS',3,'VER',4,0),
'Email',
v_rt_all_cols(i).email_id,
'IADAREMINDER',
systimestamp,
systimestamp,
0);
else
vstep_no := '6.02';
vtable_nm := 'after else insertcomm';
insert into parent_tab
(ID ,
CTEM_CODE,
CHA_CODE,
CT_CODE,
CONTACT_POINT_ID,
SOURCE,
RECEIVED_DATE,
SEND_DATE,
RETRY_COUNT)
values
(id_val,
lower(v_rt_all_cols(i).event_type),
decode(v_rt_all_cols(i).product_brand,'LTB',2,'HLX',1,'HAL',1,'BOS',3,'VER',4,0),
'Email',
v_rt_all_cols(i).email_id,
'CORRESPONDENCE',
systimestamp,
systimestamp,
0);
END if;
vstep_no := '6.11';
vtable_nm := 'before chop';
if (v_rt_all_cols(i).ACCOUNT_NUMBER is not null) then
v_rt_all_cols(i).ACCOUNT_NUMBER := 'XXXX'||substr(trim(v_rt_all_cols(i).ACCOUNT_NUMBER),length(trim(v_rt_all_cols(i).ACCOUNT_NUMBER))-3,4);
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
'IB.Correspondence.AccountNumberMasked',
v_rt_all_cols(i).ACCOUNT_NUMBER);
end if;
vstep_no := '6.1';
vtable_nm := 'before stateday';
if (v_rt_all_cols(i).crr_day is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
--'IB.Correspondence.Date.Day',
'IB.Crsp.Date.Day',
v_rt_all_cols(i).crr_day);
end if;
vstep_no := '6.2';
vtable_nm := 'before statemth';
if (v_rt_all_cols(i).crr_month is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
--'IB.Correspondence.Date.Month',
'IB.Crsp.Date.Month',
v_rt_all_cols(i).crr_month);
end if;
vstep_no := '6.3';
vtable_nm := 'before stateyear';
if (v_rt_all_cols(i).crr_year is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
--'IB.Correspondence.Date.Year',
'IB.Crsp.Date.Year',
v_rt_all_cols(i).crr_year);
end if;
vstep_no := '7';
vtable_nm := 'before type';
if (v_rt_all_cols(i).product_type is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
'IB.Product.ProductName',
v_rt_all_cols(i).product_type);
end if;
vstep_no := '9';
vtable_nm := 'before title';
if (trim(v_rt_all_cols(i).title) is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE )
values
(id_val,
'IB.Customer.Title',
trim(v_rt_all_cols(i).title));
end if;
vstep_no := '10';
vtable_nm := 'before surname';
if (v_rt_all_cols(i).surname is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
'IB.Customer.LastName',
v_rt_all_cols(i).surname);
end if;
vstep_no := '12';
vtable_nm := 'before postcd';
if (trim(v_rt_all_cols(i).POSTCODE) is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
'IB.Customer.Addr.PostCodeMasked',
substr(replace(v_rt_all_cols(i).POSTCODE,' ',''),length(replace(v_rt_all_cols(i).POSTCODE,' ',''))-2,3));
end if;
vstep_no := '13';
vtable_nm := 'before subject';
if (trim(v_rt_all_cols(i).SUBJECT) is not null) then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
'IB.Correspondence.Subject',
v_rt_all_cols(i).subject);
end if;
vstep_no := '14';
vtable_nm := 'before inactivity';
if (trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) is null or
trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) = '3' or
trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) = '6' or
trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) = '9') then
insert into child_tab
(COM_ID,
KEY,
VALUE)
values
(id_val,
'IB.Correspondence.Inactivity',
v_rt_all_cols(i).UNREAD_CORRES_PERIOD);
end if;
vstep_no := '14.1';
vtable_nm := 'after notfound';
end if;
vstep_no := '15';
vtable_nm := 'after notfound';
END LOOP;
end loop;
vstep_no := '16';
vtable_nm := 'before closecur';
CLOSE stg_cursor;
vstep_no := '17';
vtable_nm := 'before commit';
DELETE FROM table_stg;
COMMIT;
vstep_no := '18';
vtable_nm := 'after commit';
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
success_flag := 1;
vsql_code := SQLCODE;
vsql_errm := SUBSTR(sqlerrm,1,200);
error_logging_pkg.inserterrorlog('samp',vsql_code,vsql_errm, vtable_nm,vstep_no);
RAISE_APPLICATION_ERROR (-20011, 'samp '||vstep_no||' SQLERRM:'||SQLERRM);
end;
ThanksIts bit urgent
NO - it is NOT urgent. Not to us.
If you have an urgent problem you need to hire a consultant.
I have a performance issue in the below code,
Maybe you do and maybe you don't. How are we to really know? You haven't posted ANYTHING indicating that a performance issue exists. Please read the FAQ for how to post a tuning request and the info you need to provide. First and foremost you have to post SOMETHING that actually shows that a performance issue exists. Troubleshooting requires FACTS not just a subjective opinion.
where i am trying to insert the data from table_stg into target_tab and in parent_tab tables and then to child tables via cursor with bulk collect .the target_tab and parent_tab are huge tables and have a row wise trigger enabled on it .the trigger is mandatory . This timetaken for this block to execute is 5000 seconds.Now my requirement is to reduce it to 5 to 10 mins.
Personally I think 5000 seconds (about 1 hr 20 minutes) is very fast for processing 800 trillion rows of data into parent and child tables. Why do you think that is slow?
Your code has several major flaws that need to be corrected before you can even determine what, if anything, needs to be tuned.
This code has the EXIT statement at the beginning of the loop instead of at the end
FETCH stg_cursor BULK COLLECT INTO v_rt_all_cols LIMIT limit_in;
vstep_no := '4';
vtable_nm := 'after fetch';
--EXIT WHEN v_rt_all_cols.COUNT = 0;
EXIT WHEN stg_cursor%NOTFOUND;
The correct place for the %NOTFOUND test when using BULK COLLECT is at the END of the loop; that is, the last statement in the loop.
You can use a COUNT test at the start of the loop but ironically you have commented it out and have now done it wrong. Either move the NOTFOUND test to the end of the loop or remove it and uncomment the COUNT test.
WHEN OTHERS THEN
ROLLBACK;
That basically says you don't even care what problem occurs or whether the problem is for a single record of your 10,000 in the collection. You pretty much just throw away any stack trace and substitute your own message.
Your code also has NO exception handling for any of the individual steps or blocks of code.
The code you posted also begs the question of why you are using NAME=VALUE pairs for child data rows? Why aren't you using a standard relational table for this data?
As others have noted you are using slow-by-slow (row by row processing). Let's assume that PL/SQL, the bulk collect and row-by-row is actually necessary.
Then you should be constructing the parent and child records into collections and then inserting them in BULK using FORALL.
1. Create a collection for the new parent rows
2. Create a collection for the new child rows
3. For each set of LIMIT source row data
a. empty the parent and child collections
b. populate those collections with new parent/child data
c. bulk insert the parent collection into the parent table
d. bulk insert the child collection into the child table
And unless you really want to either load EVERYTHING or abandon everything you should use bulk exception handling so that the clean data gets processed and only the dirty data gets rejected. -
No Data Found Exception in bulk updates
I am trying to catch no data found exception in bulk updates when it does not find a record to update in the forall loop.
OPEN casualty;
LOOP
FETCH casulaty
BULK COLLECT INTO v_cas,v_adj,v_nbr
LIMIT 10000;
FORALL i IN 1..v_cas.count
UPDATE tpl_casualty
set casualty_amt = (select amt from tpl_adjustment where cas_adj = v_adj(i))
where cas_nbr = v_nbr(i);
EXCEPTION WHEN NO_DATA_FOUND THEN dbms_output.put_line('exception')
I get this error at the line where i have exception:
PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
begin case declare end exit for goto if loop mod null pragma
raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe
Can someone pls direct me on how to get around this?
If I do not handle this exception, the script fails when it attempts to update a record that does not exist and the error says : no data found exception.
Thanks for your help.
Edited by: user8848256 on Nov 13, 2009 6:15 PMNo Data Found isn't an exception raised when an UPDATE cannot find any records to process.
SQL%ROWCOUNT can be used to determine the number of rows affected by an update statement, but if 0 rows are updated then no exception will be raised (it's just not how things work).
If you post your actual CURSOR (casualty) declaration, it's quite possible we can help you create a single SQL statement to meet your requirement (a single SQL will be faster than your current implementation).
Have you looked in to using the MERGE command? -
Cursor with bulk collect ...
Hi experts,
CURSOR ZIP_CUR IS SELECT * FROM ZIP_MASTER WHERE ..(SUBQUERY)
OPEN ZIP_CUR;
LOOP
EXIT WHEN C1%NOTFOUND;
FETCH ZIP_CUR BULK COLLECT INTO ZIP_REC LIMIT 1000;
FOR I IN ZIP_REC.FIRST..ZIP_REC.LAST
LOOP
END LOOP
END LOOP
If there is no data in cusor then the looping after bulk collect is throughing VALUE_ERROR
but why EXIT WHEN C1%NOTFOUND not terminating procedure??
now i am using the same select statement in cursor to find the data and raise user defined exception..
is there any other way to handle in execption??
Many thanks,
Kalinga..You can try something like this -
satyaki>
satyaki>declare
2 CURSOR c_emp
3 IS
4 SELECT *
5 FROM emp_s
6 WHERE deptno in (
7 SELECT deptno
8 from emp_s
9 where job = 'ANALYST'
10 );
11
12 type emp_tt is table of emp_s%rowtype index by pls_integer;
13
14 emp_rec emp_tt;
15 begin
16
17 OPEN c_emp;
18 LOOP
19 EXIT WHEN c_emp%NOTFOUND;
20 FETCH c_emp BULK COLLECT INTO emp_rec LIMIT 1000;
21 FOR I IN 1..emp_rec.COUNT
22 LOOP
23 dbms_output.put_line('Empno: '||emp_rec(I).empno);
24 dbms_output.put_line('Ename: '||emp_rec(I).ename);
25 dbms_output.put_line('Mgr: '||emp_rec(I).mgr);
26 END LOOP;
27 END LOOP;
28 exception
29 when others then
30 dbms_output.put_line(sqlerrm);
31 end;
32 /
Empno: 7902
Ename: FORD
Mgr: 7566
Empno: 7839
Ename: KING
Mgr: 7839
Empno: 7788
Ename: SCOTT
Mgr: 7566
Empno: 7698
Ename: BLAKE
Mgr: 7839
PL/SQL procedure successfully completed.
satyaki>Regards.
Satyaki De. -
Loading data into multiple tables - Bulk collect or regular Fetch
I have a procedure to load data from one source table into eight different destination tables. The 8 tables have some of the columns of the source table with a common key.
I have run into a couple of problems and have a few questions where I would like to seek advice:
1.) Procedure with and without the BULK COLLECT clause took the same time for 100,000 records. I thought I would see improvement in performance when I include BULK COLLECT with LIMIT.
2.) Updating the Load_Flag in source_table happens only for few records and not all. I had expected all records to be updated
3.) Are there other suggestions to improve the performance? or could you provide links to other posts or articles on the web that will help me improve the code?
Notes:
1.) 8 Destination tables have at least 2 Million records each, have multiple indexes and are accessed by application in Production
2.) There is an initial load of 1 Million rows with a subsequent daily load of 10,000 rows. Daily load will have updates for existing rows (not shown in code structure below)
The structure of the procedure is as follows
Declare
dest_type is table of source_table%ROWTYPE;
dest_tab dest_type ;
iCount NUMBER;
cursor source_cur is select * from source_table FOR UPDATE OF load_flag;
BEGIN
OPEN source_cur;
LOOP
FETCH source_cur -- BULK COLLECT
INTO dest_tab -- LIMIT 1000
EXIT WHEN source_cur%NOTFOUND;
FOR i in dest_tab.FIRST .. dest_tab.LAST LOOP
<Insert into app_tab1 values key, col12, col23, col34 ;>
<Insert into app_tab2 values key, col15, col29, col31 ;>
<Insert into app_tab3 values key, col52, col93, col56 ;>
UPDATE source_table SET load_flag = 'Y' WHERE CURRENT OF source_cur ;
iCount := iCount + 1 ;
IF iCount = 1000 THEN
COMMIT ;
iCount := 0 ;
END IF;
END LOOP;
END LOOP ;
COMMIT ;
END ;
Edited by: user11368240 on Jul 14, 2009 11:08 AMAssuming you are on 10g or later, the PL/SQL compiler generates the bulk fetch for you automatically, so your code is the same as (untested):
DECLARE
iCount NUMBER;
CURSOR source_cur is select * from source_table FOR UPDATE OF load_flag;
BEGIN
OPEN source_cur;
FOR r IN source_cur
LOOP
<Insert into app_tab1 values key, col12, col23, col34 ;>
<Insert into app_tab2 values key, col15, col29, col31 ;>
<Insert into app_tab3 values key, col52, col93, col56 ;>
UPDATE source_table SET load_flag = 'Y' WHERE CURRENT OF source_cur ;
iCount := iCount + 1 ;
IF iCount = 1000 THEN
COMMIT ;
iCount := 0 ;
END IF;
END LOOP;
COMMIT ;
END ;However most of the benefit of bulk fetching would come from using the array with a FORALL expression, which the PL/SQL compiler can't automate for you.
If you are fetching 1000 rows at a time, purely from a code simplification point of view you could lose iCount and the IF...COMMIT...END IF and just commit each time after looping through the 1000-row array.
However I'm not sure how committing every 1000 rows helps restartability, even if your real code has a WHERE clause in the cursor so that it only selects rows with load_flag = 'N' or whatever. If you are worried that it will roll back all your hard work on failure, why not just commit in your exception handler? -
Retruning bulk collect into---Error
the code:
DECLARE
v_file UTL_FILE.file_type;
TYPE emp_tab_type IS TABLE OF emp%ROWTYPE;
v_row VARCHAR2 (100);
emp_tab emp_tab_type;
BEGIN
v_file := UTL_FILE.fopen ('XML_DIR', 'emp.txt', 'w');
EXECUTE IMMEDIATE 'select * from emp'
RETURNING BULK COLLECT INTO emp_tab;
FOR i IN emp_tab.FIRST .. emp_tab.LAST
LOOP
v_row :=
emp_tab.empno
|| ','
|| emp_tab.ename
|| ','
|| emp_tab.job
|| ','
|| emp_tab.mgr
|| ','
|| emp_tab.hiredate
|| ','
|| emp_tab.sal
|| ','
|| emp_tab.comm
|| ','
|| emp_tab.deptno;
UTL_FILE.put_line (v_file, v_row, TRUE);
END LOOP;
UTL_FILE.fclose (v_file);
EXCEPTION
WHEN OTHERS
THEN
UTL_FILE.fclose (v_file);
END;
the error:
ORA-06550: line 12, column 7:
PLS-00429: unsupported feature with RETURNING clause
please help!Couple of errors:
1) There is absolutely no need to use dynamic SQL here, so get rid of the EXECUTE IMMEDIATE.
2) If any error occurs, then you are hiding it from the caller by your WHEN OTHERS THEN exception handler. Just get rid of it, or use WHEN OTHERS THEN UTL_FILE.fclose (v_file); RAISE; END;
3) You have to refer to the elements of your nested table emp_tab and not to the nested table itself, so add a "(i)" to refer to the element inside the loop.
Example:
SQL> DECLARE
2 TYPE emp_tab_type IS TABLE OF emp%ROWTYPE;
3 v_row VARCHAR2 (100);
4 emp_tab emp_tab_type;
5 BEGIN
6 select *
7 BULK COLLECT INTO emp_tab
8 from emp
9 ;
10 FOR i IN emp_tab.FIRST .. emp_tab.LAST
11 LOOP
12 v_row :=
13 emp_tab(i).empno || ',' ||
14 emp_tab(i).ename || ',' ||
15 emp_tab(i).job || ',' ||
16 emp_tab(i).mgr || ',' ||
17 emp_tab(i).hiredate || ',' ||
18 emp_tab(i).sal || ',' ||
19 emp_tab(i).comm || ',' ||
20 emp_tab(i).deptno
21 ;
22 dbms_output.put_line(v_row);
23 END LOOP;
24 END;
25 /
7369,SMITH,CLERK,7902,17-12-1980 00:00:00,800,,20
7499,ALLEN,SALESMAN,7698,20-02-1981 00:00:00,1600,300,30
7521,WARD,SALESMAN,7698,22-02-1981 00:00:00,1250,500,30
7566,JONES,MANAGER,7839,02-04-1981 00:00:00,2975,,20
7654,MARTIN,SALESMAN,7698,28-09-1981 00:00:00,1250,1400,30
7698,BLAKE,MANAGER,7839,01-05-1981 00:00:00,2850,,30
7782,CLARK,MANAGER,7839,09-06-1981 00:00:00,2450,,10
7788,SCOTT,ANALYST,7566,09-12-1982 00:00:00,3000,,20
7839,KING,PRESIDENT,,17-11-1981 00:00:00,5000,,10
7844,TURNER,SALESMAN,7698,08-09-1981 00:00:00,1500,0,30
7876,ADAMS,CLERK,7788,12-01-1983 00:00:00,1100,,20
7900,JAMES,CLERK,7698,03-12-1981 00:00:00,950,,30
7902,FORD,ANALYST,7566,03-12-1981 00:00:00,3000,,20
7934,MILLER,CLERK,7782,23-01-1982 00:00:00,1300,,10
PL/SQL procedure successfully completed.Regards,
Rob. -
Hi All,
I've one doubt regarding the bulk operations using the forall statement.
Check below eample:
CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE empid_tab IS TABLE OF employees.employee_id%TYPE;
emp_sr empid_tab;
-- create an exception handler for ORA-24381
errors NUMBER;
dml_errors EXCEPTION;
PRAGMA EXCEPTION_INIT(dml_errors, -24381);
BEGIN
SELECT employee_id BULK COLLECT INTO emp_sr FROM emp_temp
WHERE hire_date < '30-DEC-94';
-- add '_SR' to the job_id of the most senior employees
FORALL i IN emp_sr.FIRST..emp_sr.LAST SAVE EXCEPTIONS
UPDATE emp_temp SET job_id = job_id || '_SR'
WHERE emp_sr(i) = emp_temp.employee_id;
-- If any errors occurred during the FORALL SAVE EXCEPTIONS,
-- a single exception is raised when the statement completes.
EXCEPTION
WHEN dml_errors THEN -- Now we figure out what failed and why.
errors := SQL%BULK_EXCEPTIONS.COUNT;
DBMS_OUTPUT.PUT_LINE('Number of statements that failed: ' || errors);
FOR i IN 1..errors LOOP
DBMS_OUTPUT.PUT_LINE('Error #' || i || ' occurred during '||
'iteration #' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
DBMS_OUTPUT.PUT_LINE('Error message is ' ||
SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
Here we update using bulk collect & the exceptions for each iterations are kept separately.
In case, I want to know whether the sql statements in each array are executed separately or all the statements are executed in bulk?
Thanks
DeepakMay this will answer it...
FORALL - documentation -
How can I see error when execute UPDATE with BULK COLLECT
Hi
I have a code
CURSOR c_renov_eleg IS
SELECT t2.ROWID
FROM mytable t2
WHERE BLA BLA BLA
OPEN c_renov_eleg;
LOOP
FETCH c_renov_eleg BULK COLLECT
INTO w_rowid LIMIT 1000;
FORALL i IN 1 .. w_rowid.COUNT
UPDATE mytable
SET id_baixa_elegibilidade = K_SCNOB_BXA_RENOVACAO,
column01 = arr_ciclo(1),
dt_ultima_atualizacao = SYSDATE,
cd_usuario_atualizacao = USER
WHERE ROWID = w_rowid(i);
COMMIT;
EXIT WHEN c_renov_eleg%NOTFOUND;
END LOOP;How can I to sse when and where have some error ? , in Exception return what record ?How can I to sse when and where have some error
?Have a look at
[url=http://download.oracle.com/docs/cd/B28359_01/appd
ev.111/b28370/tuning.htm#i49099]Handling FORALL
Exceptions (%BULK_EXCEPTIONS Attribute).btw. just never ever commit in a for loop ;)
(Tubby is just too fast ;))
Hi , thank all
btw. just never ever commit in a for loopWhen I must to COMMIT using BULK COLLECT ?
Maybe you are looking for
-
Memory upgrade on the NB550D-11D - 4GB RAM are possible
To anyone who's thinking about a memory upgrade on the NB550D: The NB550D supports up to 4GB of memory, not only 2GB as mentioned by Toshiba in their specifications. A memory upgrade to 2GB is _only limited_ by the pre-installed Windows 7 Starter OS,
-
DBA role and system privileges
I created a new user (PIPPO) with the default dba role in my db. I know that the dba_role has the SELECT ANY TABLE and INSERT ANY TABLE system privileges. I expeperienced that if I select a table of another schema on a simple sqlplus session everythi
-
Photoshop vs Photoshop elements -which to learn?
Hi, I am getting started and I don't think I need the full power of Photoshop yet, but on the other hand I want to invest my limited time wisely. If I learn to use Photoshop Elements first, will it help, hinder, or be neutral as far as learning Phot
-
Transaction launcher : Activity clip board integration
Hi All, Anyone please tell me what is "Activity clip board integration" while creating a Transaction Launcher for a navigational link in web IC scenario using Wizard!. What the check box for "save data in Activity clip board" means?. any hint please
-
Camera Plus app download installation problem
I purchased Camera Plus app and I recieved the receipt in my email, put when I made the purchase, I was unable to download the app to my phone. How do I go back and download the app I have purchased?