Use Cursor variable to insert with a loop in a store procedure - oracle

I have a store procedure and I need to take all id´s from a table and insert new rows in other table with those id´s but i dont´t understand well the function cursor
PROCEDURE INSERTMDCGENERAL AS
idCat NUMERIC;
CURSOR cur IS
SELECT ID_CAT_FILTROS_TALENTO into idCat FROM MDC_CAT_FILTROS_TALENTO;
BEGIN
FOR v_reg IN cur LOOP
INSERT INTO MDC_FILTROS_TALENTO(ID_FILTRO,ID_CAT_FILTROS_TALENTO)
VALUES(SEC_MDC_FILTROS_TALENTO.NextVal,idCat);
END LOOP;
COMMIT;
END INSERTMDCGENERAL;

There is rarely any point in doing anything more complex than:
PROCEDURE INSERTMDCGENERAL AS
BEGIN
INSERT INTO MDC_FILTROS_TALENTO
(ID_FILTRO,ID_CAT_FILTROS_TALENTO)
SELECT SEC_MDC_FILTROS_TALENTO.NextVal
, ID_CAT_FILTROS_TALENTO
FROM MDC_CAT_FILTROS_TALENTO;
COMMIT;
END INSERTMDCGENERAL;
This should work in most cases. Only if you are dealing with millions of rows is it likely that you will need to embellish this. Even then you should not use a cursor loop and Row-By-Row processing: that is vastly more inefficient.

This might be what you are expecting...
PROCEDURE INSERTMDCGENERAL AS
idCat NUMERIC;
CURSOR cur IS SELECT ID_CAT_FILTROS_TALENTO FROM MDC_CAT_FILTROS_TALENTO;
BEGIN
open cur;
loop
fetch cur into idCat;
exit when cur%notfound;
INSERT INTO MDC_FILTROS_TALENTO(ID_FILTRO,ID_CAT_FILTROS_TALENTO)
VALUES(SEC_MDC_FILTROS_TALENTO.NextVal,idCat);
END LOOP;
close cur;
COMMIT;
END INSERTMDCGENERAL;

Related

Returning Multiple Columns in stored procedure - ORACLE 11.2 Up

Just wondering how I go about returning multiple columns from the database with this stored proc, Thanks.
is
cursor sample_cur is --this can be your select statement
select name as today from names;
begin
for rec in sample_cur loop
-- step by step for each record you return in your cursor
dbms_output.put_line(rec.name);
end loop;
end;
Cursor can return multiple columns, for example:
procedure list_something(p_result out sys_refcursor) as
begin
open p_result for
select t.column1,
t.column2
from MY_TABLE t
where t.column3 is not null;
end;
Next you can iterate thought this cursor from Java/.Net, etc.
Apart from Manushin's answer, If you strictly wants answer in your format, You may try below -
is
cursor sample_cur is --this can be your select statement
select name, other_column1, other_column2 as today from names;
begin
for rec in sample_cur loop
-- step by step for each record you return in your cursor
dbms_output.put_line(rec.name || rec.other_column1 || rec.other_column2);
end loop;
end;

How to execute Stored Procedure inside Stored Procedure with Cursor in Oracle

I am new in Oracle,
In SQL Server I can easily execute a stored procedure inside storedprocedure
even using a cursor.
now I can't figure it out in Oracle here is my code below.
CREATE OR REPLACE PROCEDURE ZSP_INSMASTERDATASTM
AS
l_total INTEGER := 10000;
CURSOR c1
IS
SELECT DISTINCT PRODFROMTO FROM DJ_P9945LINKS;
l_PRODFROMTO c1%ROWTYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO l_PRODFROMTO;
EXIT WHEN c1%NOTFOUND;
EXECUTE ZSP_GETMASTERDATASTM (l_PRODFROMTO);
EXIT WHEN l_total <= 0;
END LOOP;
CLOSE c1;
END ZSP_INSMASTERDATASTM;
i got error on execute ZSP_GETMASTERDATASTM (l_PRODFROMTO);
Just remove EXECUTE. However, note that your loop will NEVER exit because L_TOTAL is never going to be less than zero - you should fix that.
Otherwise, consider using cursor FOR loop as it is simpler to maintain - you don't have to declare a cursor variable, open cursor, fetch, take care about exiting the loop, close the cursor. Have a look at this example:
CREATE OR REPLACE PROCEDURE zsp_insmasterdatastm
AS
BEGIN
FOR cur_r IN (SELECT DISTINCT prodfromto FROM dj_p9945links)
LOOP
zsp_getmasterdatastm (cur_r.prodfromto);
END LOOP;
END;
Quite simpler, isn't it?

Oracle Open Cursor Execution time

I'm trying to figure out how long this cursor takes to execute. However, I'm getting the same start and end time.
Please note I didn't include the actual sql statement. But I'm sure it is takes quite long time to execute.
PROCEDURE GetData (p1 IN VARCHAR2,myREFCURSOR OUT SYS_REFCURSOR)
IS
DynamicStatement CLOB;
BEGIN
INSERT INTO TimeTable VALUES ('StartTime',SYSDATE);
COMMIT;
OPEN myREFCURSOR FOR DynamicStatement;
INSERT INTO TimeTable VALUES ('EndTime',SYSDATE);
COMMIT;
END;
A Ref Cursor is a pointer to a chunk of memory where a query is stashed. Opening one is just an assignment operation, it doesn't execute the query. That's why it appears to take no time at all.
If you want to see how long it takes to run the actual query you need to FETCH records into some record variable.
PROCEDURE GetData (p1 IN VARCHAR2,myREFCURSOR OUT SYS_REFCURSOR)
IS
DynamicStatement CLOB;
type rec is record (id number, blah varchar2(128));
lrec rec;
BEGIN
INSERT INTO TimeTable VALUES ('StartTime',SYSDATE);
COMMIT;
OPEN myREFCURSOR FOR DynamicStatement;
loop
fetch myREFCURSOR into rec;
exit when myREFCURSOR%notfound;
end loop;
close myREFCURSOR;
INSERT INTO TimeTable VALUES ('EndTime',SYSDATE);
COMMIT;
END;
Obviously the record variable must match the projection of your query. Given that you're executing DynamicStatement that may be difficult.

PL/SQL Printing Cursor Elements

I tried several ways and looked lots of codes, but I couldn't do it. I have 2 tables
Declare
v_ay varchar2(32);
cursor c_clone_time is
select beko_user_ref
from user_role;
begin
open c_clone_time;
fetch c_clone_time into v_ay
WHILE c_clone_time%FOUND LOOP
dbms_output.put_line (v_ay);
end while;
end;
I'm just trying to print the cursor values, but it is always failing. Can anyone help me ?
There are several spots(syntactical, semantical, and logical errors) in your code needed attention:
Minor one. The fetch c_clone_time into v_ay statement not terminated by semicolon ;.
You end while as any other loop statement with end loop; clause, not end while or end for as you might think.
To be able to print the contents of the cursor and successfully get out of the loop, you need to fetch from that cursor inside the loop as well, otherwise you are stuck with a never-ending loop:
Having said that your code might look look this:
declare
v_ay varchar2(32);
cursor c_clone_time is
select beko_user_ref
from user_role;
begin
open c_clone_time;
fetch c_clone_time into v_ay;
while c_clone_time%found loop
dbms_output.put_line (v_ay);
fetch c_clone_time into v_ay;
end loop;
end;
Test case:
create table user_role(
beko_user_ref varchar2(100)
);
insert into user_role(beko_user_ref)
select dbms_random.string('l', 7)
from dual
connect by level <= 7;
commit;
Print the cursor:
set serveroutput on;
clear screen;
declare
v_ay varchar2(32);
cursor c_clone_time is
select beko_user_ref
from user_role;
begin
open c_clone_time;
fetch c_clone_time into v_ay;
while c_clone_time%found loop
dbms_output.put_line (v_ay);
fetch c_clone_time into v_ay;
end loop;
end;
Result:
anonymous block completed
kcjhygy
cgunlmt
ofxaspd
qwqvnxx
nxjdrli
luevaqk
xvdocpr

How do I run multiple scripts one after another in Oracle?

I have the following script:
ALTER TABLE ODANBIRM
ADD (OBID NUMBER(10, 0) );
----------------------------------------------------------------------------
CREATE OR REPLACE TRIGGER TR_OB_INC
BEFORE INSERT ON ODANBIRM
FOR EACH ROW
BEGIN
SELECT SEQ_OB.NEXTVAL INTO :NEW.OBID FROM DUAL;
END;
-----------------------------------------------------------------------------
DECLARE
CURSOR CUR IS
SELECT ROWID AS RID FROM ODANBIRM;
RC CUR%ROWTYPE;
BEGIN
OPEN CUR;
LOOP
FETCH CUR INTO RC;
EXIT WHEN CUR%NOTFOUND;
UPDATE ODANBIRM SET OBID=SEQ_OB.NEXTVAL WHERE ROWID=RC.RID;
END LOOP;
CLOSE CUR;
COMMIT;
END;
As you can see I have three different scripts (I've seperated them with dashed lines.) If I run this the first script runs but the second script, where I want to create a trigger fails saying "Encountered symbol "DECLARE"". If I take the trigger creation script away I get no error and the first and the last scripts run with no problem. What do I have to do to run them all without getting errors?
EDIT: I then realised that the second script should be just like this:
UPDATE ODANBIRM SET OBID=SEQ_OB.NEXTVAL;
So doing this simple thing in a loop is a waste of time and inefficient. I've once heard that one should use as much SQL and as less PL SQL as possible for efficiency. I think it's a good idea.
I think it's / on the line immediately following the end of a script. It's needed on ALL end of script lines for PL blocks, including the last. so...
However, do not put it on SQL statements; as it will run it twice (as Benoit points out in comments below!)
ALTER TABLE ODANBIRM
ADD (OBID NUMBER(10, 0) );
/
CREATE OR REPLACE TRIGGER TR_OB_INC
BEFORE INSERT ON ODANBIRM
FOR EACH ROW
BEGIN
SELECT SEQ_OB.NEXTVAL INTO :NEW.OBID FROM DUAL;
END;
/
DECLARE
CURSOR CUR IS
SELECT ROWID AS RID FROM ODANBIRM;
RC CUR%ROWTYPE;
BEGIN
OPEN CUR;
LOOP
FETCH CUR INTO RC;
EXIT WHEN CUR%NOTFOUND;
UPDATE ODANBIRM SET OBID=SEQ_OB.NEXTVAL WHERE ROWID=RC.RID;
END LOOP;
CLOSE CUR;
COMMIT;
END;
/
Shouldn't your anonymous block just be:
UPDATE ODANBIRM
SET OBID=SEQ_OB.NEXTVAL;

Resources