FORALL ...
Does any one know whether "FORALL" (bulkload) supported in Oracle 8i distributed environment (using db link) in Open VMS platform.
You can use it with the following three syntaxes:
1) forall <index_name> in <lower_bound>..<high_bound> <sql_stmt>
2) forall <index_name> in indices of <collection> between <lower_bound> and <high_bound> <sql_stmt>
3) forall <index_name> in values of <collection> <sql_stmt>
So... if you do not want to use a collection .. then you can use only the first version....
forall x in 1..400
delete.....
Greetings...
Sim
Similar Messages
-
Hi,
I have written this procedure and I am getting
LINE/COL ERROR
69/5 PL/SQL: SQL Statement ignored
83/11 PL/SQL: ORA-00947: not enough values
CREATE OR REPLACE PROCEDURE f_t_s (P_F IN VARCHAR2)
IS
TYPE quote_cols_rt IS RECORD
twitter_gid twitter.twitter_gid%TYPE,
twitter_xid twitter.twitter_xid%TYPE,
origin_location_type twitter.origin_location_type%TYPE,
destination_location_type twitter.destination_location_type%TYPE,
is_hazardous twitter.is_hazardous%TYPE,
perspective twitter.perspective%TYPE,
twitter_option twitter.twitter_option%TYPE,
servprov_gid twitter.servprov_gid%TYPE,
origin_search_value twitter.origin_search_value%TYPE,
destination_search_value twitter.destination_search_value%TYPE,
domain_name twitter.domain_name%TYPE,
is_customer_rates_only twitter.is_customer_rates_only%TYPE
TYPE twitter_cols_tt IS TABLE OF twitter_cols_rt INDEX BY PLS_INTEGER;
twitter_cols_t twitter_cols_tt;
BEGIN
SELECT all_spec twitter_gid,
SUBSTR(all_spec,7) twitter_xid,
'location_code' origin_location_type,
'location_code' destination_location_type,
'N' is_hazardous,
'B' perspective,
'O' twitter_option,
'INDIA.'||servprov_xid servprov_gid,
SUBSTR(tm,1,2) ||':'||SUBSTR(tm,3) origin_search_value,
Location_xid destination_search_value,
'INDIA' domain_name,
'N' is_customer_rates_only
BULK COLLECT INTO twitter_cols_t
FROM
(SELECT x.*,
Q.twitter_gid
FROM
(SELECT 'INDIA.FS_'||H.servprov_xid||'_'||D.Location_xid||'_'||T.tm all_spec,
servprov_xid ,
tm ,
Location_xid
FROM
(SELECT Location_xid
FROM location
WHERE location_xid IN ('1')
AND domain_name ='INDIA'
) D,
(SELECT servprov_xid
FROM servprov
WHERE(servprov_gid LIKE 'P_F%'
AND SUBSTR(servprov_xid,2,1) IN ('2'))
OR servprov_gid ='INDIA.FRESHMISC'
) H,
(SELECT lpad(rownum-1,2,'0') ||'00' tm FROM sea WHERE rownum<25
UNION
SELECT lpad(rownum-1,2,'0') ||'30' tm FROM sea WHERE rownum<25
) T
) x,
(SELECT * FROM twitter WHERE twitter_gid LIKE 'INDIA.FS%'
) Q
WHERE x.all_spec=Q.twitter_gid(+)
WHERE twitter_gid IS NULL;
FORALL i in 1 .. twitter_cols_t.count
--LOOP
INSERT
INTO twitter
(twitter_gid ,
twitter_xid ,
origin_location_type ,
destination_location_type,
is_hazardous ,
perspective ,
twitter_option ,
servprov_gid ,
origin_search_value ,
destination_search_value ,
domain_name ,
is_customer_rates_only)
VALUES
twitter_cols_t (i);
--END LOOP;
END f_t_s;
Any idea where I am doing mistake
Thanks in Advance,
DIDIHi,
That was my typing mistake....
This is correct code
CREATE OR REPLACE PROCEDURE f_t_s (P_F IN VARCHAR2)
IS
TYPE twitter_cols_rt IS RECORD
twitter_gid twitter.twitter_gid%TYPE,
twitter_xid twitter.twitter_xid%TYPE,
origin_location_type twitter.origin_location_type%TYPE,
destination_location_type twitter.destination_location_type%TYPE,
is_hazardous twitter.is_hazardous%TYPE,
perspective twitter.perspective%TYPE,
twitter_option twitter.twitter_option%TYPE,
servprov_gid twitter.servprov_gid%TYPE,
origin_search_value twitter.origin_search_value%TYPE,
destination_search_value twitter.destination_search_value%TYPE,
domain_name twitter.domain_name%TYPE,
is_customer_rates_only twitter.is_customer_rates_only%TYPE
TYPE twitter_cols_tt IS TABLE OF twitter_cols_rt INDEX BY PLS_INTEGER;
twitter_cols_t twitter_cols_tt;
BEGIN
SELECT all_spec twitter_gid,
SUBSTR(all_spec,7) twitter_xid,
'location_code' origin_location_type,
'location_code' destination_location_type,
'N' is_hazardous,
'B' perspective,
'O' twitter_option,
'INDIA.'||servprov_xid servprov_gid,
SUBSTR(tm,1,2) ||':'||SUBSTR(tm,3) origin_search_value,
Location_xid destination_search_value,
'INDIA' domain_name,
'N' is_customer_rates_only
BULK COLLECT INTO twitter_cols_t
FROM
(SELECT x.*,
Q.twitter_gid
FROM
(SELECT 'INDIA.FS_'||H.servprov_xid||'_'||D.Location_xid||'_'||T.tm all_spec,
servprov_xid ,
tm ,
Location_xid
FROM
(SELECT Location_xid
FROM location
WHERE location_xid IN ('1')
AND domain_name ='INDIA'
) D,
(SELECT servprov_xid
FROM servprov
WHERE(servprov_gid LIKE 'P_F%'
AND SUBSTR(servprov_xid,2,1) IN ('2'))
OR servprov_gid ='INDIA.FRESHMISC'
) H,
(SELECT lpad(rownum-1,2,'0') ||'00' tm FROM sea WHERE rownum<25
UNION
SELECT lpad(rownum-1,2,'0') ||'30' tm FROM sea WHERE rownum<25
) T
) x,
(SELECT * FROM twitter WHERE twitter_gid LIKE 'INDIA.FS%'
) Q
WHERE x.all_spec=Q.twitter_gid(+)
WHERE twitter_gid IS NULL;
FORALL i in 1 .. twitter_cols_t.count
--LOOP
INSERT
INTO twitter
(twitter_gid ,
twitter_xid ,
origin_location_type ,
destination_location_type,
is_hazardous ,
perspective ,
twitter_option ,
servprov_gid ,
origin_search_value ,
destination_search_value ,
domain_name ,
is_customer_rates_only)
VALUES
twitter_cols_t (i);
--END LOOP;
END f_t_s;
Thanks,
DIDI -
Deletion is taking long time using forall
Hi,
i am inserting and deleting the rows using forall. insert taking less time to inset the rows but while coming to
deletion it is taking more than 5 days long time to delete 18.5 million rows in a table using forall.
the main table having 70 million rows.
the code is..
FETCH ref_typ BULK COLLECT INTO l_id_tbl LIMIT 10000;
begin
FORALL i in 1..l_id_tbl.COUNT
INSERT INTO change_test (id,
history,
transaction,
date)
VALUES (seq.nextval,
'CHANGE_HIS',
l_id_tbl(i),
sysdate);
exception
when others then
null;
end;
begin
FoRALL i in 1..l_id_tbl.COUNT
DELETE FROM change_his
where id = l_id_tbl(i);
exception
when others then
null;
end;
end loop;
so please give me a good solution to delete the rows less than 5 days..Why are you wanting to do this using BULK COLLECT and FORALL?
Why not just "insert ... select ..." and "delete ..."?
Loading records into expensive PGA memory to insert them back on the database is bound to be slower (and use more server resources) than just doing a straight insert ... select ... statement.
Explain exactly what you are trying to do.
Re: 2. How do I ask a question on the forums? -
Hello All,
May i know why the following example from Oracle documentation is failing.
CREATE TABLE coords (x NUMBER, y NUMBER);
CREATE TYPE Pair AS OBJECT (m NUMBER, n NUMBER);
DECLARE
TYPE PairTab IS TABLE OF Pair;
pairs PairTab := PairTab(Pair(1,2), Pair(3,4), Pair(5,6));
TYPE NumTab IS TABLE OF NUMBER;
nums NumTab := NumTab(1, 2, 3);
BEGIN
/* The following statement succeeds. */
FORALL i in 1..3
UPDATE coords SET (x, y) = (pairs(i).m, pairs(i).n)
WHERE x = nums(i);
END;
Error:
Error starting at line 37 in command:
DECLARE
TYPE PairTab IS TABLE OF Pair;
pairs PairTab := PairTab(Pair(1,2), Pair(3,4), Pair(5,6));
TYPE NumTab IS TABLE OF NUMBER;
nums NumTab := NumTab(1, 2, 3);
BEGIN
/* The following statement succeeds. */
FORALL i in 1..3
UPDATE coords SET (x, y) = (pairs(i).m, pairs(i).n)
WHERE x = nums(i);
END;
Error report:
ORA-06550: line 9, column 34:
PL/SQL: ORA-01767: UPDATE ... SET expression must be a subquery
ORA-06550: line 9, column 7:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Thank you.Based on your advise i did the below example,
DECLARE
TYPE PairTab IS TABLE OF Pair;
pairs PairTab := PairTab(Pair(1,2), Pair(3,4), Pair(5,6),Pair(7,8),Pair(9,10));
TYPE NumTab IS TABLE OF NUMBER;
nums NumTab := NumTab(1,2,3,4,5);
vnum1 NUMBER;
vnum2 number;
BEGIN
FORALL i IN 1 .. 5
UPDATE coords
SET (x, y) = (SELECT pairs(i).m, pairs(i).n
FROM dual)
WHERE x = nums(i);
END;
INSERT INTO coords VALUES(1,10);
INSERT INTO coords VALUES(2,10);
insert into coords values(3,10);
INSERT INTO coords VALUES(4,10);
INSERT INTO coords VALUES(5,10);
commit;
After insertng the data into coords table i execute the above plsql block i got the below output.I wonder how come rows 2,3 & 5 are updated with 9,10.
Output:
1
2
9
10
9
10
7
8
9
10 -
Hi All,
I am using FORALL for inserting 40000 records from the file to the table. After reading data from the file it has been stored in type Table array, But while executing FORALL statement its giving ora-00600. error.
It is a memory error, some where I read to using LIMIT in fetch. But I am not using any fetch or Cursor. Can any body Help.
SKM
=================== ================= Package Code
create or replace package insertpackage as
TYPE tabSNO IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER;
TYPE tabSNO1 IS TABLE OF VARCHAR2(1) INDEX BY BINARY_INTEGER;
TYPE tabSDATE IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER;
TYPE SNO IS TABLE OF NUMBER(5) INDEX BY BINARY_INTEGER;
procedure insertpro(snoArray IN SNO, sDate IN tabSDATE, sArray IN tabSNO, sArray1 IN tabSNO1);
end insertpackage;
create or replace package body insertpackage as
procedure insertpro(snoArray IN SNO, sDate IN tabSDATE, sArray IN tabSNO, sArray1 IN tabSNO1) is
begin
forall i in 1..sArray.last
insert into test(s_no, s_date, s_co, s_type)
values(snoArray(i), TO_DATE(sDate(i),'YYYY-MM-DD HH24.MI.SS'), sArray(i), sArray1(i));
end;
end insertpackage;
/Hi User,
The error
implementation restriction: cannot reference fields of BULK In-BIND table of recordsis because bulk bind cannot use table of composite types.
Please See the below,
http://dba-blog.blogspot.com/2005/08/using-of-bulk-collect-and-forall-for.html
And rewrite your code like this,
DECLARE
CURSOR EMP_CUR
IS
SELECT EMPNO, ENAME
FROM EMP;
TYPE TAB_EMP_EMPNO IS TABLE OF EMP.EMPNO%TYPE;
V_TAB_EMPNO TAB_EMP_EMPNO;
TYPE TAB_EMP_ENAME IS TABLE OF EMP.ENAME%TYPE;
V_TAB_ENAME TAB_EMP_ENAME;
BEGIN
OPEN EMP_CUR;
FETCH EMP_CUR BULK COLLECT INTO V_TAB_EMPNO, V_TAB_ENAME;
FORALL I IN V_TAB_EMPNO.FIRST .. V_TAB_EMPNO.LAST
INSERT INTO EMP_TEMP
(EMPNO, ENAME
VALUES (V_TAB_EMPNO (I), V_TAB_ENAME (I)
CLOSE EMP_CUR;
END;Thanks,
Shankar -
Using Sequence in FORALL Statement
I'm using a package to get the nextval in a sequence object. Basically, it is a function that returns select user_seq.nextval from dual.
But I get 'column not allowed here' error. PL/SQL: ORA-00984: column not allowed here
OPEN users_ins ;
LOOP
FETCH naf_users_ins
BULK COLLECT
INTO arr_person_key
, arr_person_id
, arr_first_name
, arr_middle_name
, arr_last_name
, arr_username
, arr_user_status_seq
, arr_creation_date
, arr_comments
LIMIT 100 ;
FORALL idx IN 1 .. arr_person_key.COUNT
SAVE EXCEPTIONS
INSERT INTO users
( user_seq
, person_key
, person_id
, first_name
, middle_name
, last_name
, username
, user_status_seq
, creation_date
, comments
VALUES ( *pkg_admin.get_nextval*
, arr_person_key(idx)
, arr_person_id(idx)
, arr_first_name(idx)
, arr_middle_name(idx)
, arr_last_name(idx)
, arr_username(idx)
, arr_user_status_seq(idx)
, arr_creation_date(idx)
, arr_comments(idx)
EXIT WHEN users_ins%NOTFOUND ;
END LOOP ;
CLOSE users_ins;
c/code]Hi,
I've recently completed a similar task, but I declared a collection with the rowtype of the table. I also added the sequence in the query of my cursor. Take a look at the following example.
CREATE OR REPLACE PROCEDURE Insert_OR_ExternalService
IS
TYPE externalService_tbl IS TABLE OF OR_ExternalService%ROWTYPE;
externalService externalService_tbl;
CURSOR OR_ExternalServiceCursor
IS
select
SEQ_ID.NEXTVAL as "Id",
column as "ExternalId",
column as "ExternalSystem",
from table1
where ...;
BEGIN
OPEN OR_ExternalServiceCursor;
LOOP
FETCH OR_ExternalServiceCursor BULK COLLECT INTO externalService LIMIT 1000;
FORALL i IN 1 .. externalService.count
INSERT INTO OR_ExternalService values externalService(i);
COMMIT;
EXIT WHEN OR_ExternalServiceCursor%NOTFOUND;
END LOOP;
CLOSE OR_ExternalServiceCursor;
END; -
PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL
See code below: Have googled the error but not sure how to fix the code. ANy help would be most greatful.
DECLARE
CURSOR c1
IS
SELECT /*+ parallel(tr,8)*/ DISTINCT tr.ACC ACC, tr.MET_ID METID, to_char(max(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0))),'YYYY') dt
FROM CTTR0FIL_CDC tr
JOIN transaction_action_sd sd on (sd.TRANSACTION_CODE = tr.RESULT)
WHERE sd.ACTION_TYPE = 'PAYMENT'
and to_char(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0)),'YYYY') = '1987'
GROUP BY tr.ACC, tr.MET_ID, to_char(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0)),'YYYY');
SUBTYPE PAY_DATES IS c1%ROWTYPE;
TYPE TMP_TABLE IS TABLE OF PAY_DATES INDEX BY PLS_INTEGER;
TBROWS TMP_TABLE;
temp VARCHAR2(100);
Begin
DBMS_OUTPUT.ENABLE(10000);
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO TBROWS LIMIT 1000;
FORALL i IN 1..TBROWS.COUNT
SELECT /*+ parallel(da,8)*/ da.ACC INTO temp
FROM CTDA0FIL_CDC da
WHERE da.ACC = TBROWS(i).ACC AND da.MET_ID = TBROWS(i).MET_ID AND da.ACC = '07000006P' AND da.MET_ID = 4;
DBMS_OUTPUT.PUT_LINE('inside');
EXIT WHEN c1%notfound;
END LOOP;
CLOSE c1;
END;
Thanks
SimonI tried using a normal for loop instead of a forall loop (see code below). But this came up the error also see below. Or can I not use selects in this way???
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO tbrows LIMIT 1000;
FOR i IN TBROWS.FIRST .. TBROWS.LAST
LOOP
SELECT /*+ parallel(da,8)*/ da.ACC INTO temp
FROM CTDA0FIL_CDC da WHERE da.ACC = TBROWS(i).ACC AND da.MET_ID = TBROWS(i).MET_ID AND da.ACC = '07000006P' AND da.MET_ID = 4;
DBMS_OUTPUT.PUT_LINE('inside');
EXIT WHEN c1%notfound;
END LOOP;
END LOOP;
CLOSE c1;
END;
Error:
DECLARE
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 24 -
FORALL MERGE statement works in local database but not over database link
Given "list", a collection of NUMBER's, the following FORALL ... MERGE statement should copy the appropriate data if the record specified by the list exists on both databases.
forall i in 1..list.count
merge into tbl@remote t
using (select * from tbl
where id = list(i)) s
on (s.id = t.id)
when matched then
update set
t.status = s.status
when not matched then
insert (id, status)
values (s.id, s.status);
But this does not work. No exceptions, but target table's record is unchanged and "sql%rowcount" is 0.
If the target table is in the local database, the exact same statement works:
forall i in 1..list.count
merge into tbl2 t
using (select * from tbl
where id = list(i)) s
on (s.id = t.id)
when matched then
update set
t.status = s.status
when not matched then
insert (id, status)
values (s.id, s.status);
Does anyone have a clue why this may be a problem?
Both databases are on Oracle 10g.
Edited by: user652538 on 2009. 6. 12 오전 11:29
Edited by: user652538 on 2009. 6. 12 오전 11:31
Edited by: user652538 on 2009. 6. 12 오전 11:45Should throw an error in my opinion. The underlying reason for not working is basically because of
SQL> merge into t@remote t1
using ( select sys.odcinumberlist (1) from dual) t2
on (1 = 1)
when matched
then
update set i = 1
Error at line 4
ORA-22804: remote operations not permitted on object tables or user-defined type columnsSame reason as e.g.
insert into t@remote select * from table(sys.odcinumberlist(1,2,3))doesn't work. -
Issue in using Cursor+Dynamic SQL+ Bulk collect +FORALL
Hi,
I have a dynamic query which I need to use as a cursor to fetch records that inturn need to be inserted into a staging table.
The issue I am facing is I am not sure how to declare the variable to fetch the records into. Since I am using a dynamic cursor how do I declare it?
My code looks something like this -
TYPE c_details_tbl_type IS REF CURSOR;
c_details c_details_tbl_type;
TYPE c_det_tbl_type IS TABLE OF c_details%ROWTYPE INDEX BY PLS_INTEGER;
c_det_tbl c_det_tbl_type; -- ???
BEGIN
v_string1 := 'SELECT....'
v_string2 := ' UNION ALL SELECT....'
v_string3 := 'AND ....'
v_string := v_string1||v_string2||v_string3;
OPEN c_details FOR v_string;
LOOP
FETCH c_details BULK COLLECT
INTO c_det_tbl LIMIT 1000;
IF (c_det_tbl.COUNT > 0) THEN
DELETE FROM STG;
FORALL i IN 1..c_det_tbl.COUNT
INSERT INTO STG
VALUES (c_det_tbl(i));
END IF;
EXIT WHEN c_details%NOTFOUND;
END LOOP;
CLOSE c_details;
END
ThanksWhy the bulk collect? All that this does is slow down the read process (SELECT) and write process (INSERT).
Data selected needs (as a collection) to be pushed into the PGA memory of the PL/SQL engine. And then that very same data needs to be pushed again by the PL/SQL engine back to the database to be inserted. Why?
It is a lot faster, needs a lot less resources, with fewer moving parts, to simply instruct the SQL engine to do both these steps using a single INSERT..SELECT statement. And this can support parallel DML too for scalability when data volumes get large.
It is also pretty easy to make a single SQL statement like this dynamic and even support bind variables.
Simplicity is the ultimate form of elegance. Pushing data needlessly around is not simple and thus not a very elegant way to address the problem. -
Error in self increment varible value using "FORALL"
CREATE OR REPLACE PROCEDURE BULK_COLLCT_PASS
AS
TYPE VAR_TYP IS VARRAY (32767) OF VARCHAR2 (32767);
V_DSH_CM_NUMBER VAR_TYP;
V_DSH_DATE VAR_TYP;
V_DSH_TIME VAR_TYP;
V_DSD_CM_NUMBER VAR_TYP;
V_PLU_CODE VAR_TYP;
V_DSD_DATE VAR_TYP;
V_str_id VAR_TYP;
LN_ITM NUMBER:=0;
str_id number := 30001;
CURSOR CUR_DBMG_SAL_HEAD
IS
SELECT DSH.CM_NUMBER,D_DSH_CM_DATE, D_DSH_CM_TIME
FROM DBMG_SAL_HEAD DSH
WHERE ROWNUM<6;
BEGIN
OPEN CUR_DBMG_SAL_HEAD;
LOOP
FETCH CUR_DBMG_SAL_HEAD BULK COLLECT
INTO V_DSH_CM_NUMBER,
V_DSH_DATE,
V_DSH_TIME;
FOR indx IN V_DSH_CM_NUMBER.FIRST .. V_DSH_CM_NUMBER.LAST
LOOP
SELECT CM_NUMBER, PLU_CODE,V_DSH_DATE(indx)
BULK COLLECT
INTO V_DSD_CM_NUMBER, V_PLU_CODE,V_DSD_DATE
FROM DBMG_SAL_DETL DSD
WHERE DSD.CM_NUMBER = V_DSH_CM_NUMBER(indx);
--block1
Ln_Itm := 0;
FOR ind IN 1..V_DSD_CM_NUMBER.COUNT
loop
INSERT INTO PC_ALL_TAB
VALUES(V_DSH_CM_NUMBER(indx),
V_DSD_DATE(ind),
V_DSD_CM_NUMBER(ind),
V_PLU_CODE(ind),
LN_ITM,
str_id
LN_ITM := LN_ITM +1;
end loop;
--block2
END LOOP;
EXIT WHEN CUR_DBMG_SAL_HEAD%NOTFOUND;
END LOOP;
commit;
CLOSE CUR_DBMG_SAL_HEAD;
DBMS_OUTPUT.PUT_LINE('COMPLETE..!');
END ;
Hi,
I am using above code in which when code between "--block1 & --block2" is incrementing ln_itm value by 1 each time.
so that after completion of code o/p is as below.
SELECT DSH_CM_NUMBER, LN_ITM FROM PC_ALL_TAB;
DSH_CM_NUMBER LN_ITM
1 4177424 0
2 4177422 0
3 4177426 0
4 4177426 1
5 4177426 2
6 4177425 0
7 4177427 0
8 4177427 1
9 4177427 2
for each repeating value of cm_number its incresing by 1.
but i wan to change "--block1 to --block2" in "FORALL". i did this but i m nt getting o/p is incresing value of ln_itm.
kindly help me...
code after changed to "FORALL"
CREATE OR REPLACE PROCEDURE BULK_COLLCT_PASS
AS
TYPE VAR_TYP IS VARRAY (32767) OF VARCHAR2 (32767);
V_DSH_CM_NUMBER VAR_TYP;
V_DSH_DATE VAR_TYP;
V_DSH_TIME VAR_TYP;
V_DSD_CM_NUMBER VAR_TYP;
V_PLU_CODE VAR_TYP;
V_DSD_DATE VAR_TYP;
V_str_id VAR_TYP;
LN_ITM NUMBER:=0;
str_id number := 30001;
CURSOR CUR_DBMG_SAL_HEAD
IS
SELECT DSH.CM_NUMBER,D_DSH_CM_DATE, D_DSH_CM_TIME
FROM DBMG_SAL_HEAD DSH
WHERE ROWNUM<6;
BEGIN
OPEN CUR_DBMG_SAL_HEAD;
LOOP
FETCH CUR_DBMG_SAL_HEAD BULK COLLECT
INTO V_DSH_CM_NUMBER,
V_DSH_DATE,
V_DSH_TIME;
FOR indx IN V_DSH_CM_NUMBER.FIRST .. V_DSH_CM_NUMBER.LAST
LOOP
SELECT CM_NUMBER, PLU_CODE,V_DSH_DATE(indx)
BULK COLLECT
INTO V_DSD_CM_NUMBER, V_PLU_CODE,V_DSD_DATE
FROM DBMG_SAL_DETL DSD
WHERE DSD.CM_NUMBER = V_DSH_CM_NUMBER(indx);
--block1
/*Ln_Itm := 0;
FOR ind IN 1..V_DSD_CM_NUMBER.COUNT
loop
INSERT INTO PC_ALL_TAB
VALUES(V_DSH_CM_NUMBER(indx),
V_DSD_DATE(ind),
V_DSD_CM_NUMBER(ind),
V_PLU_CODE(ind),
LN_ITM,
str_id
LN_ITM := LN_ITM +1;
end loop; */
FORALL ind IN 1..V_DSD_CM_NUMBER.COUNT
INSERT INTO PC_ALL_TAB
VALUES(V_DSH_CM_NUMBER(indx),
V_DSD_DATE(ind),
V_DSD_CM_NUMBER(ind),
V_PLU_CODE(ind),
LN_ITM,
str_id
LN_ITM := LN_ITM +1;
--block2
END LOOP;
EXIT WHEN CUR_DBMG_SAL_HEAD%NOTFOUND;
END LOOP;
commit;
CLOSE CUR_DBMG_SAL_HEAD;
DBMS_OUTPUT.PUT_LINE('COMPLETE..!');
END ;
o/p :- SELECT DSH_CM_NUMBER, LN_ITM FROM PC_ALL_TAB;
DSH_CM_NUMBER LN_ITM
1 4177424 0
2 4177422 1
3 4177426 2
4 4177426 2
5 4177426 2
6 4177425 3
7 4177427 4
8 4177427 4
9 4177427 4
I need result as below...but using "FORALL"
DSH_CM_NUMBER LN_ITM
1 4177424 0
2 4177422 0
3 4177426 0
4 4177426 1
5 4177426 2
6 4177425 0
7 4177427 0
8 4177427 1
9 4177427 2Double post
How to increment value using "FORALL" instead of for loop -
Hi all
i have a problem.Actually i'm giving a test problem here.While executing this i'm getting ora 66550 error .What wrong i'm doing?
say col1 and col2 is column of tab1.
type test is table of number;
a_test test:=test(8,9);
cursor c1(test number) is
select col1 from tab1
where col2=test;
p1 c1%rowtype;
begin
forall i in 1 .. a_test.count
for p1 in c1(a_test(i)) loop
insert into b_test values(a_test(i),p1.col1)
end loop;
end;
Thanks in advancebp wrote:
Hi all
i have a problem.Actually i'm giving a test problem here.While executing this i'm getting ora 66550 error .What wrong i'm doing?
say col1 and col2 is column of tab1.
type test is table of number;
a_test test:=test(8,9);
cursor c1(test number) is
select col1 from tab1
where col2=test;
p1 c1%rowtype;
begin
forall i in 1 .. a_test.count
for p1 in c1(a_test(i)) loop
insert into b_test values(a_test(i),p1.col1)
end loop;
end;
test@ORA10G>
test@ORA10G>
test@ORA10G> select * from tab1;
C COL2
a 6
b 7
c 8
d 9
e 10
5 rows selected.
test@ORA10G>
test@ORA10G>
test@ORA10G> --
test@ORA10G> declare
2 type test is table of number;
3 a_test test:=test(8,9);
4 begin
5 forall i in 1 .. a_test.count
6 insert into b_test (x,y)
7 select col2, col1
8 from tab1
9 where col2 = a_test(i);
10 end;
11 /
PL/SQL procedure successfully completed.
test@ORA10G>
test@ORA10G> select * from b_test;
X Y
8 c
9 d
2 rows selected.
test@ORA10G>
test@ORA10G>isotope -
BULKING and FORALL statement does not pass values to non DML statements.
Hi
I've got million rows that i need to manapulate and insert into various procedures depending on the bussiness rule to be applied, but my dilemma is that the BULIKNG with a combination of a FORALL statement its not compatible(only considers straightforward DML calls) or the the FORALL does not like other SQL statements or calls as it prefers only DML's.
Below is code fragment that is problamatic as the compiler keeps sending me this error: PLS-00201: identifier 'INDX' must be declared
I want to manupulate data on the implicity cursor and call a procedure to do other stuff which don't use INSERT/DELETE or UPDATE statements.
Declare
TYPE tab_person_id is of table of number(15);
l_person_id tab_person_id;
BEGIN
SELECT person_id
BULK COLLECT INTO l_person_id
FROM person_details; /*-Million records-*/
FORALL indx IN l_tdtl.FIRST..l_tdtl.LAST
pj_pkg.ins_intf
(p_user => p_user,
p_typ_cd => '00',
p_person_id => l_person(indx)
Commit;
END;
How do I pass this value 'l_person(indx)' on the package procudure ?
Thanks
Amos@prabodh:
SQL> declare
2 TYPE tab_person_id is of table of number(15) index by pls_integer;
3 begin
4 null;
5 end;
6 /
TYPE tab_person_id is of table of number(15) index by pls_integer;
ERROR at line 2:
ORA-06550: line 2, column 23:
PLS-00103: Encountered the symbol "OF" when expecting one of the following:
( array limited new private range record VARRAY_ char_base
number_base decimal date_base clob_base blob_base bfile_base
table ref object fixed varying opaque sparse
The symbol "OF" was ignored.Check What you are posting.
@ qwestion: What is your Database Version? It is a implementation restriction. -
How can I run two DML in one FORALL statement?
How can I run 1) select 2) update in one FORALL for each item as below?
OPEN FXCUR;
LOOP
FETCH FXCUR BULK COLLECT INTO v_ims_trde_oids LIMIT 1000;
EXIT WHEN v_ims_trde_oids.COUNT() = 0;
FORALL i IN v_ims_trde_oids.FIRST .. v_ims_trde_oids.LAST
SELECT EXTRACTVALUE(XMLTYPE(CNTNT),'/InboundGTMXML/ProcessingIndicators/ClientCLSEligibleIndicator') INTO v_cls_ind
FROM IMS_TOMS_MSGE WHERE ims_trde_oid = v_ims_trde_oids(i);
IF v_cls_ind IS NOT NULL THEN
v_cls_ind := '~2136|S|'||v_cls_ind||'|';
UPDATE ims_alctn_hstry SET CHNGE_DATA_1 =concat(CHNGE_DATA_1,v_cls_ind)
WHERE ims_trde_hstry_id = (select max(ims_trde_hstry_id) from ims_alctn_hstry where ims_trde_oid=v_ims_trde_oids(i));
DBMS_OUTPUT.PUT_LINE('Trade oid: '||v_ims_trde_oids(i)||' CLS Eligible Indicator: '||v_cls_ind);
END IF;
END LOOP;
CLOSE FXCUR;Your help will be appreciated.
Thanks
Edited by: PhoenixBai on Aug 6, 2010 6:05 PMI came through this forum while googling on the issue of 'using two DML's in one FORALL statement.
Thanks for all the useful information guys.
I need to extend this functionality a bit.
My present scenario is as follows:
FOR I in 1..collection1.count Loop
BEGIN
insert into tab1(col1)
values collection1(I) ;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR('ERROR AT'||collection1(I));
END;
BEGIN
UPDATE tab2
SET col1 = collection1(I);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR('ERROR AT'||collection1(I));
END;
commit;
END LOOP;
I need to use the FORALL functionality in this scenario, but without using the SAVE EXCEPTIONS clause keeping in mind that I also need to get value in the
collection that led to the error.Also, the each INSERT statement has to be followed by an UPDATE and then the cycle goes on(Hence I cannot use 2 FORALL statements for INSERT and UPDATE coz then all the INSERT will be performed at once and similarly the UPDATEs). So I created something like this:
DECLARE
l_stmt varchar2(1000);
BEGIN
l_stmt := 'BEGIN '||
'insert into tab1(col1) '||
'values collection1(I) ; '||
'EXCEPTION '||
'WHEN OTHERS THEN '||
'RAISE_APPLICATION_ERROR(''ERROR AT''|| :1); '||
'END; '||
'BEGIN '||
'UPDATE tab2 '||
'SET col1 = :1; '||
'EXCEPTION '||
'WHEN OTHERS THEN '||
'RAISE_APPLICATION_ERROR(''ERROR AT''|| :1); '||
'END;'
FORALL I in 1..collection1.count
EXECUTE IMMEDIATE l_stmt USING Collection1(SQL%BULK_EXCEPTIONS(1).ERROR_INDEX);
END;
Will this approach work? Or is there any better aproach to this? I am trying to avoid the traditional FOR ..LOOP to achieve better performance of query -
Where to put the commit in the FORALL BULK COLLECT LOOP
Hi,
Have the following LOOP code using FORALL and bulk collect, but didnt know where to put the
'commit' :
open f_viewed;
LOOP
fetch f_viewed bulk collect into f_viewed_rec LIMIT 2000;
forall i in 1..f_viewed_rec.count
insert into jwoodman.jw_job_history_112300
values f_viewed_rec(i);
--commit; [Can I put this 'commit' here? - Jenny]
EXIT when f_viewed%NOTFOUND;
END LOOP;
commit;
Thanks,
- Jennymc**** wrote:
Bulk collect normally used with large data sets. If you have less dataset such as 1000-2000 records then you canot get such a performance improvent using bulk collect.(Please see oracle documents for this)
When you update records Oracle acquire exclusive lock for that. So if you use commit inside the loop then it will process number of records defined by limit parameter at ones and then commit those changes.
That will release all locks acquired by Oracle and also teh memory used to keep those uncommited transactions.
If you use commit outside the loop,
Just assume that you insert 100,000 records, all those records will store in oracle memory and it will affect all other users performance as well.
Further more if you update 100,000 records then it will hold exclusive lock for all 100,000 records addtion to the usage of the oracle memory.
I am using this for telco application which we process over 30 million complex records (one row has 234 columns).
When we work with large data sets we do not depends with the oracle basic rollback function. because when you keep records without commit itb uses oracle memory and badly slowdown all other processes.Hi mc****,
What a load of dangerous and inaccurate rubbish to be telling a new Oracle developer. Commit processing should be driven by the logical unit of a transaction. This should hold true whether that transaction involves a few rows or millions. If, and only if, the transaction is so large that it affects the size constraints of the database resources, in particular, rollback or redo space, then you can consider breaking that transaction up to smaller transactions.
Why is frequent committing undesirable I hear you ask?
First of all it is hugely wasteful of rollback or redo space. This is because while the database is capable of locking at a row level, redo is written at a block level, which means that if you update, delete or insert a million rows and commit after each individual statement, then that is a million blocks that need to go into redo. As many of these rows will be in the same block, if you instead do these as one transaction, then the same block in redo can be transacted upon, making the operation more efficient. True, locks will be held for longer, but if this is new data being done in batches then users will rarely be inconvenienced. If locking is a problem then I would suggest that you should be looking at how you are doing your processing.
Secondly, committing brings into play one of the major serialization points in the database, log sync. When a transaction is committed, the log buffer needs to be written to disc. This occurs serially for multiple commits. Each commit has to wait until the commit before has completed. This becomes even more of a bottleneck if you are using Data Guard in SYNC mode, as the commit cycle does not complete until the remote log is notified as written.
This then brings us two rules of thumb that will always lead a developer in the right direction.
1. Commit as infrequently as possible, usually at the logical unit of a transaction
2. When building transactions, first of all seek to do it using straight SQL (CTAS, insert select, update where etc). If this can't be easily achieved, then use PL/SQL bulk operations.
Regards
Andre -
FORALL Exception handling problem
Hi All,
I have one doubt in forall exception handling. I have gone through the SAVE EXCEPTION for bulk collect but i have one more query
BEGIN
FORALL j IN l_tab.first .. l_tab.last
INSERT INTO exception_test
VALUES (l_tab(i));
EXCEPTION
END;
My requirement is when an exception occurs, i ant to print the values of the collection.
e.g. say l_tab (j).emp_number, l_tab (j).emp_id.
How is that possible?
Thanks
Samarth
Edited by: 950810 on Mar 12, 2013 7:28 PM>
I have one doubt in forall exception handling. I have gone through the SAVE EXCEPTION for bulk collect but i have one more query
BEGIN
FORALL j IN l_tab.first .. l_tab.last
INSERT INTO exception_test
VALUES (l_tab(i));
EXCEPTION
END;
My requirement is when an exception occurs, i ant to print the values of the collection.
e.g. say l_tab (j).emp_number, l_tab (j).emp_id.
How is that possible?
>
Post the code you are using. You didn't post the FORALL that is using SAVE EXCEPTIONS.
The SQL%BULK_EXCEPTIONS associative array that you get has the INDEX of the collection element that caused the exception.
So you need to use those indexes to index into the original collection to get whatever values are in it.
One index from the exception array is:
SQL%BULK_EXCEPTIONS(i).error_index So if your original collection is named 'myCollection' you would reference that collection value as:
myCollection(SQL%BULK_EXCEPTIONS(i).error_index); See 'Handling FORALL Exceptions (%BULK_EXCEPTIONS Attribute)' in the PL/SQL Language doc
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/tuning.htm#i49099
>
All exceptions raised during the execution are saved in the cursor attribute %BULK_EXCEPTIONS, which stores a collection of records. Each record has two fields:
%BULK_EXCEPTIONS(i).ERROR_INDEX holds the iteration of the FORALL statement during which the exception was raised.
%BULK_EXCEPTIONS(i).ERROR_CODE holds the corresponding Oracle Database error code.
The values stored by %BULK_EXCEPTIONS always refer to the most recently executed FORALL statement. The number of exceptions is saved in %BULK_EXCEPTIONS.COUNT. Its subscripts range from 1 to COUNT.
The individual error messages, or any substitution arguments, are not saved, but the error message text can looked up using ERROR_CODE with SQLERRM as shown in Example 12-9.
You might need to work backward to determine which collection element was used in the iteration that caused an exception. For example, if you use the INDICES OF clause to process a sparse collection, you must step through the elements one by one to find the one corresponding to %BULK_EXCEPTIONS(i).ERROR_INDEX. If you use the VALUES OF clause to process a subset of elements, you must find the element in the index collection whose subscript matches %BULK_EXCEPTIONS(i).ERROR_INDEX, and then use that element's value as the subscript to find the erroneous element in the original collection. -
Hi All,
Deski Formula: =(<Discrepancy Count(S# of DCF Resolved)>+<Discrepancy Count(S# of DCF UnResolved - All)>)/Sum(<Discrepancy Count(S# of DCF Resolved)>+<Discrepancy Count(S# of DCF UnResolved - All)>) ForAll (<Site(S# of Page Saved Imcomplete)> , <Site Country> ,<Inv Name>)
in this formula,the site country and inv name are detail object
if i use the same formula in webi the values are not matching with deski.i made detail to dimension objects but not working. what are the workaround need to do to achieve the same in webi?help me pls urgent requirementcan you change the opendoc syntax to point at a one of the specific server and see if it works? also how is the load balance configured - does it use sticky cookies? perhaps the balancer is not maintaining the server session details
Maybe you are looking for
-
Storing pdf documents by pages in oracle 9i usinf jsp
Hi ,,, When pdf doc is gets uploaded it needs to be saved to the db by pages (Ex. if a doc. has 2 pages 2 records need to be saved to db). Client should be able to download several documents at once or several pages of the certain document how to spl
-
Lion(?) appears to have destroyed my drive
Ok, so last Friday (6 days ago), I installed Lion on my home Mac Pro. The install went off without a hitch, and everything seemed to be working pretty well. Then today I woke my computer from sleep, and began working on a motion graphics piece in C4
-
Music files properties inaccurate
Hello everybody, New to the forum but not to BB! Trying out here as I failed finding answers anywhere else as I usually do So, basically put: all my songs are correctly labeled in my iTunes library, meaning the Title, the Artist, the Album, the Year,
-
I have installed ACR 4.5 under Photoshop CS3 and Bridge. Under Plug In get info, ACR 4.5xx is displaed so I can assume it installed correctly. However, within Bridge or Lightroom 2, ACR version 4.4 is displayed as a choice but not ACR 4.5. Can someon
-
Need To Wipe System & Reinstall How...
I need to wipe a system and reinstall on an older titanium powerbook. What is the best way to take everything I need off the same powerbook ( mail, calendar, itunes ect.) so it can be put back into place after I reinstall the system? I have apple's b