I was trying to display hiredate using lead function with cursor however I'm getting this error message - PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL. Please guide me.
SET SERVEROUTPUT ON
DECLARE
CURSOR C_11 IS SELECT * FROM EMP;
TYPE DD IS TABLE OF EMP%ROWTYPE;
CC DD;
VV EMP.HIREDATE%TYPE;
GG EMP.HIREDATE%TYPE;
BEGIN
OPEN C_11;
LOOP
FETCH C_11 BULK COLLECT INTO CC LIMIT 1000;
FORALL I IN CC.FIRST..CC.LAST
SELECT HIREDATE,LEAD(HIREDATE) OVER(ORDER BY HIREDATE) INTO VV,GG FROM EMP;
DBMS_OUTPUT.PUT_LINE (VV ||' '||GG);
EXIT WHEN C_11%NOTFOUND;
END LOOP;
CLOSE C_11;
END;
PLS-00435: DML statement without BULK In-BIND cannot be used inside
FORALL.
FORALL statement is only used for INSERT / UPDATE or DELETE . It doesnot support SELECT.
Read the FORALL Restrictions:
https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/forall_statement.htm
Alternatively you can do it as shown below:
DECLARE
CURSOR c_11 IS
SELECT hiredate,
LEAD(hiredate) OVER( ORDER BY hiredate ) DT
FROM emp;
TYPE dd IS TABLE OF c_11%rowtype;
cc dd;
BEGIN
OPEN c_11;
LOOP
FETCH c_11 BULK COLLECT INTO cc LIMIT 100;
FOR i IN 1..cc.count
LOOP
dbms_output.put_line(cc(i).hiredate || ' -- ' || cc(i).dt);
END LOOP;
EXIT WHEN c_11%notfound;
END LOOP;
CLOSE c_11;
END;
I need to write a procedure that will insert thousands of rows in a table and use the auto generated id resulted from these rows and use it in other inserts.
I used a for loop in which I save the sequence id in a variable then use it in my inserts.
declare
first_id integer;
BEGIN
FOR texts in (select distinct text from table_texts )
LOOP
first_id := SEQ_IDS_OBJECTID.NEXTVAL;
INSERT INTO table_1(id,some_fields)
VALUES (first_id, 'blablabla');
insert into table_2 (id,text_field)
VALUES (first_id, texts.text);
END LOOP;
commit;
END;
I think that this is not the ideal way to achieve what I need. Also when I enter the code in TOAD , I get the following warning :
Rule 4809 (A loop that contains DML statements should be refactored to use BULK COLLECT and FORALL)
Is there better way to do it?
EDIT:
the above code was simplified. But I think I have to expose more of it to explain the case :
declare
first_id integer;
second_id integer;
BEGIN
FOR texts in (select distinct text1 , text2 from mdf )
LOOP
first_id := XAKTA.SEQ_IDS_OBJECTID.NEXTVAL;
select id_1 into second_id from table_3 where field_1 =texts.text1 ;
INSERT INTO table_1(id_1,id_2,some_fields)
VALUES (first_id ,second_id ,'blablabla');
insert into table_2 (id,text1,text2)
VALUES (first_id, texts.text1,texts.text2);
END LOOP;
commit;
END;
You can use FORALL to insert batches of items from your cursor:
DECLARE
TYPE texts_tab IS TABLE OF table_texts.text%TYPE;
TYPE ids_tab IS TABLE OF table_2.id%TYPE;
p_texts texts_tab;
p_ids ids_tab;
CURSOR c IS
SELECT DISTINCT text FROM table_texts;
BEGIN
OPEN c;
LOOP
FETCH c BULK COLLECT INTO p_texts LIMIT 100;
FORALL i IN 1 .. p_texts.COUNT
INSERT INTO table_2 ( id, text_field )
VALUES ( SEQ_IDS_OBJECTID.NEXTVAL, p_texts(i) )
RETURNING id BULK COLLECT INTO p_ids;
FORALL i IN 1 .. p_ids.COUNT
INSERT INTO table_1( id, some_fields )
VALUES ( p_ids(i), 'blablabla' );
EXIT WHEN c%NOTFOUND;
END LOOP;
CLOSE c;
COMMIT;
END;
/
db<>fiddle here
I am currently using the following code to do a bulk insert of 50 million rows:
declare cnt number;
BEGIN
select max(run_ver_issue_id) into cnt from "ABHINAV"."MV_RUN_VER_ISSUE";
FOR x IN 1 .. 50000000 LOOP
INSERT INTO "ABHINAV"."MV_RUN_VER_ISSUE" NOLOGGING ("RUN_VER_ISSUE_ID","CUST_ISSUE_ID","TITLE","ORIGINAL_ISSUE_ID","SOURCE_FILE_LINE","DISPLAY_TEXT","RUN_VER_ID","SANDBOX_SRC_FILE_ID","ACCOUNT_ID","ISSUE_STATE","CURRENT_SEVERITY","INSERT_TS","MODIFIED_TS","CWE_ID","TEMPLATE_FILE_ID","TEMPLATE_FILE_LINE","CURRENT_EXPLOIT_LEVEL","CNT","SOURCE_FUNCTION_PROTOTYPE","SOURCE_RELATIVE_LOCATION","SOURCE_SCOPE","PROCEDURE_NAME","PROCEDURE_HASH","PROTOTYPE_HASH","STATEMENT_HASH","STATEMENT_HASH_COUNT","STATEMENT_HASH_ORDINAL","SUBMODULE_PATH") VALUES (x+cnt,2,..);
END LOOP;
END;
It takes almost 6 hours it to finish. The table does have an index on RUN_VER_ISSUE_ID, but still doesn't help. I tried using FORALL, getting an error PLS-00430: FORALL iteration variable X is not allowed in this context for the below code:
declare cnt number;
BEGIN
select max(run_ver_issue_id) into cnt from "ABHINAV"."MV_RUN_VER_ISSUE";
FORALL x IN 1 .. 5
INSERT INTO "ABHINAV"."MV_RUN_VER_ISSUE" NOLOGGING ("RUN_VER_ISSUE_ID","CUST_ISSUE_ID","TITLE","ORIGINAL_ISSUE_ID","SOURCE_FILE_LINE","DISPLAY_TEXT","RUN_VER_ID","SANDBOX_SRC_FILE_ID","ACCOUNT_ID","ISSUE_STATE","CURRENT_SEVERITY","INSERT_TS","MODIFIED_TS","CWE_ID","TEMPLATE_FILE_ID","TEMPLATE_FILE_LINE","CURRENT_EXPLOIT_LEVEL","CNT","SOURCE_FUNCTION_PROTOTYPE","SOURCE_RELATIVE_LOCATION","SOURCE_SCOPE","PROCEDURE_NAME","PROCEDURE_HASH","PROTOTYPE_HASH","STATEMENT_HASH","STATEMENT_HASH_COUNT","STATEMENT_HASH_ORDINAL","SUBMODULE_PATH") VALUES (x+cnt,2,.....);
END;
I would request you to please provide your suggestions and comments as to how I can speed this up.
you may use this:
declare
p_array_size number := 100000;
type array is table of number;
l_data ARRAY;
cursor c is select rownum seq_no from dual connect by rownum <= p_array_size;
cnt number;
begin
open c;
loop
select max(RUN_VER_ISSUE_ID) into cnt from "ABHINAV"."MV_RUN_VER_ISSUE";
fetch c bulk collect into l_data limit p_array_size;
forall x IN 1 .. l_data.count
insert into "ABHINAV"."MV_RUN_VER_ISSUE"("RUN_VER_ISSUE_ID","CUST_ISSUE_ID","TITLE","ORIGINAL_ISSUE_ID","SOURCE_FILE_LINE","DISPLAY_TEXT","RUN_VER_ID","SANDBOX_SRC_FILE_ID","ACCOUNT_ID","ISSUE_STATE","CURRENT_SEVERITY","INSERT_TS","MODIFIED_TS","CWE_ID","TEMPLATE_FILE_ID","TEMPLATE_FILE_LINE","CURRENT_EXPLOIT_LEVEL","CNT","SOURCE_FUNCTION_PROTOTYPE","SOURCE_RELATIVE_LOCATION","SOURCE_SCOPE","PROCEDURE_NAME","PROCEDURE_HASH","PROTOTYPE_HASH","STATEMENT_HASH","STATEMENT_HASH_COUNT","STATEMENT_HASH_ORDINAL","SUBMODULE_PATH")
values(l_data(x)+cnt,2,'0pJDFy1viDnN2Ku66XPl458gKakF4xz4pTawwoOZYCt0yR2YOw7tH1Mk3oKQ7ynuyasbBjBXr1teBbBdmIsJReIM3kbzWY7H4c6CVgVaw',NULL,230969,'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',74228,2,6120,8096,581270,'26-Sep-12 01:30:00','21-Feb-00 03:52:00',7531,1,NULL,5203,12726,'NAxr4jgRDRnDJiNKp10sfdntA8MKBU0xwWEInpm4yOTjvj5aRHt4fcNujL777cw74AuLEeEskCgzbkZNk2fcaTpBmYl8GtrUsB7KH5Wtfb4Elo8tfpRD7Eh7CjjkTdke7opjX5IBBEDSlxyinbcSLrtK7FuOBXDWM0tMGuq86VlZc27obCFBJyFSGi5FFgAA0PWETUoDR7HerxaisVUzmWuAb1HTKHgdTucNFzvtsxcCXKBwlpE3I7S8G2rhEGs2KOajFOoiB7ZbTPOFSNh7qUEY83GowgJo2lDChWr5tCtQqeJGUyrA2e8kXQ3Oh8Ov28C6muKtSbQFLFrJ0WlQYnDBvXqrHes0wT8rkHMEedJ1NIrf2HBBbI06p2qlO7RCr878gngE3bPiocJAvNHJfnkwnDMu06wda3ZkMmXBL1HTfdPyWfcL44OHzPsQdD4yr6HiM8vP7bzzxXNMBWDuDim8oeAc6o1jByEzgzyztvX6mas4UxAXG4Hm8iWodaoYwUixaFw4vr8qpp7jp8HfYbgC7J6pH4PQKV8krjvGdW3o33tHHBFS6Ytxobi31iSIcSZ2WQcfMzddLi61OmPB3zdKRABt57hj1wbIoQxHUsbsmtHRLZ3fT1V37RLQXfu3GzgjuPLYWxVdQRM7T4v5rhecY7c53ilFIr6KIfeIZ0DY5SGXLWqLoYfN7ZrHHEAONrId0GMeRO2Y0j4uF8j4RXJUpk81wUlFgnlGFkCSKwnXLK7aqYMPri4w0Bp0GixZ7E1JHWOlWDM40VXw5jBz7KnkClba6IaDJNgT8UeUDRHNhNVDiXIWSHLJAUzQqGN5RmG7X6ttpRgQPFpBPXX3UsA758WWSB7d4cNAniSp2jHMhSIl2kRkEnXkm8yuk0B08tDIIEZvDj6zvSsLqDuCmUwpUPcYdsofagnP8WIFoH1fKe4AbbzgUXzTCPgMjKkRvBKoXUgnpWtuNCoz2cosaxDDSOUEuBgX58UltaybzjqS1jMs3F3X3Ewjm2M0wWTeLjuXc3WLjF7OBQAvdDxLUQDRIGDFeeadqbe1gdC7ONr3gZY7w3mYwTJVlCaA0P4qRxhDUDItZNgLEpx4unTsO5Te51PD3YeicmqHlJbxknhjYpciOhfWYrmYGvCCl0xyga0hZ74EDiL1iLQjr1ADRa40SmUh1ufvfbZzcr5OpkttKmeeA75LjDIi58WvajJk0o1bKTgos7OTmhs5LT3cMZ3XJV4An4xtoCNGK4Ktreh6rXTnmHRCQ3HP2kfOTykNT2T8b6vS8rtnsqaLy862mTDBYKnqichIMvyN8fhEaQX0eP5iAs7jn2SrEybNAVOpYzaz6bRFVk1POPaHlkRysYOxGs2r8qumcpSs8ylD3YN2nPCc6OVpBCRw2YT1wozwOOA03r8hDNNz3ZhrNPY6EoW28mOApChU2QHcV63L4S5RiKJYOpAAOeApF5xGOuYnT8Lc4YUHVuwpNSZmxclNL6dzA3MJtCl88J3sZWcuigBgWiDjLUgeVnObW55nj7bYWkZB6UqmBCNNaWaIVkchCMtHNnvHnnoonLuBQTpnHdWy0kXUwY2o3Bd5jnDOQgEMVkiWgoOhRVMbt0cRvxQwSMYkkMyarg1OuYxAGhtY7Orsu1YEhs3MITDhzm4NDDEusaIXdDSaNl4u2ScTYKIsYchLBYo7fa2pvx4oUuaOHAi2oNPRR05zP5pqycSsDpnkEz6YIYBQiZaRgVRp407t83',48913,'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','Aox4fssjHKLaZwTS0Bq',57753,NULL,'C:\DOCS\TEMP75');
exit when c%notfound;
end loop;
close c;
commit;
end;
A table is having 100 million records and I need to update a column by adding 10% into the salary of each employee. when I execute update statement I am getting this error:
ORA-01562: Failed to extend rollback segment
How can I update this column for the best performance result?
update employee
set salary = salary + (salary*10/100)
OR
declare
i number(10);
limit number(10) := 100000;
begin
for i in 1 .. limit loop
update employee
set salary = salary + (salary*10/100)
where rownum = i;
limit := limit + 100000;
end loop;
end;
Looks like you are using Oracle version 8i or prior, as the rollback segments have been replaced with undo segments from Oracle 9i onwards.
To solve the problem, I would suggest you to check the trace file to see which rollback segment is creating the problem, then create a bigger rollback segment depending upon the update transaction size.
Try this:
DECLARE
CURSOR CUR
IS
SELECT ROWID, A.*
FROM YOUR_SALARY_TABLE A;
TYPE CUR_TYPE IS TABLE OF CUR%ROWTYPE
INDEX BY PLS_INTEGER;
L_CUR CUR_TYPE;
LIM NUMBER := 100000; -- Update chunk size
BEGIN
OPEN CUR;
LOOP
FETCH CUR BULK COLLECT INTO L_CUR LIMIT LIM;
FOR INDX IN 1 .. L_CUR.COUNT
LOOP
UPDATE YOUR_SALARY_TABLE S
SET S.SALARY_COLUMN = S.SALARY_COLUMN * 2 -- Multiplying here
WHERE ROWID = L_CUR (INDX).ROWID;
END LOOP;
COMMIT;
EXIT WHEN L_CUR.COUNT < LIM;
END LOOP;
CLOSE CUR;
END;
You can try this approach: link
Information about parallel: link
We can use FORALL also to achieve what is required. Hope this below snippet helps.
DROP TABLE test_so1
/
CREATE TABLE TEST_SO1
( COL1 NUMBER, COL2 VARCHAR2(100)
)
/
--Insert values
INSERT INTO TEST_SO1
SELECT LEVEL,'AVRAJIT'||LEVEL FROM DUAL CONNECT BY LEVEL < 10000
/
--FORALL UPDATE
DECLARE
type TEST_REC
IS
RECORD
(
COL1 NUMBER,
COL2 VARCHAR2(100),
col3 VARCHAR2(100));
type TEST_TAB
IS
TABLE OF TEST_REC;
LV_TAB TEST_TAB;
CURSOR LV_CUR
IS
SELECT col1,col2,rowid FROM TEST_SO1;
BEGIN
OPEN LV_CUR;
LOOP
FETCH LV_CUR BULK COLLECT INTO LV_TAB LIMIT 1000;
EXIT
WHEN LV_TAB.COUNT=0;
FORALL I IN LV_TAB.FIRST..LV_TAB.LAST
UPDATE TEST_SO1 SET COL2 = 'shubhojit' WHERE ROWID = lv_tab(i).col3;
COMMIT;
END LOOP;
END;
/
I need to process close to 60k records of an Oracle table through a stored procedure. The processing is that for each such row, I need to delete and update a row in a second table and insert a row in a third table.
Using cursor looping, the procedure takes around 6-8 hours to complete. If I switch to Bulk Collect with Limit, the execution time is reduced but processing is not correct. Following is the bulk collect version of the procedure
create or replace procedure myproc()
is
cursor c1 is select col1,col2,col3 from tab1 where col4=3;
type t1 is table of c1%rowtype;
v_t1 t1;
begin
open c1;
loop
fetch c1 bulk collect into v_t1 limit 1000;
exit when v_t1.count=0;
forall i in 1..v_t1.count
delete from tab2 where tab2.col1=v_t1(i).col1;
commit;
forall i in 1..v_t1.count
update tab2 set tab2.col1=v_t1(i).col1 where tab2.col2=v_t1(i).col2;
commit;
forall i in 1..v_t1.count
insert into tab3 values(v_t1(i).col1,v_t1(i).col2,v_t1(i).col3);
commit;
end loop;
close c2;
end;
For around 20k of these records, the first delete operation is processed correctly but subsequent update and insert is not processed. For the remaining 40k records all three operations are processed correctly.
Am I missing something? Also what is the maximum LIMIT value I can use with Bulk Collect?
You should try using SAVE EXCEPTIONS clause of FORALL, something like (untested):
create or replace procedure myproc
as
cursor c1 is select col1,col2,col3 from tab1 where col4=3;
type t1 is table of c1%rowtype;
v_t1 t1;
dml_errors EXCEPTION;
PRAGMA exception_init(dml_errors, -24381);
l_errors number;
l_errno number;
l_msg varchar2(4000);
l_idx number;
begin
open c1;
loop
fetch c1 bulk collect into v_t1 limit 1000;
-- process v_t1 data
BEGIN
forall i in 1..v_t1.count SAVE EXCEPTIONS
delete from tab2 where tab2.col1=v_t1(i).col1;
commit;
EXCEPTION
when DML_ERRORS then
l_errors := sql%bulk_exceptions.count;
for i in 1 .. l_errors
loop
l_errno := sql%bulk_exceptions(i).error_code;
l_msg := sqlerrm(-l_errno);
l_idx := sql%bulk_exceptions(i).error_index;
-- log these to a table maybe, or just output
end loop;
END;
exit when c1%notfound;
end loop;
close c2;
end;