How to execute Stored Procedure inside Stored Procedure with Cursor in Oracle - 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?

Related

How to execute script conditionally in oracle?

I have a long DDL data migration script which has 15 transaction blocks. For each block, it takes data from one table and then inserts into another table.
But now I have come across a scenario in which the database does not have that table. In this case my script does not compile even.
What I actually want is to check and return early if the table does not exist. If it does, then only continue further execution.
But the script does not even compiles since it has statement which contains a table name which is non-existent in that particular database.
After some googling, I found that we can use those statements in EXECUTE IMMEDIATE block. I have tried this, but haven't been able to get it compiled.
Here is the block -
DECLARE
V_OBJECT_NAME1 VARCHAR2(50);
V_STRING VARCHAR2(1000);
V_CONTINUE Boolean;
BEGIN
V_CONTINUE := true;
SELECT TABLE_NAME INTO V_OBJECT_NAME1 FROM USER_TABLES WHERE TABLE_NAME = 'OOLD_SFWID_CHG_LOG_HEADER';
EXCEPTION WHEN NO_DATA_FOUND THEN
V_CONTINUE := false;
IF V_CONTINUE then
--scubbber code
V_STRING := 'DECLARE
CURSOR C1 IS
SELECT * FROM OOLD_SFWID_CHG_LOG_HEADER;
BEGIN
OPEN C1;
CLOSE C1;
END;';
EXECUTE IMMEDIATE V_STRING
END IF;
END;
Please suggest how can we write it..

Multiple line output in pl/sql

I have a PL/SQL file that has a loop structure.
The script is as follows.
SET SERVEROUTPUT ON
declare
c_id employee.id%type;
c_name employee.name%type;
c_address employee.address%type;
CURSOR c_employee is
SELECT id, name, address from employee;
begin
open c_employee;
LOOP
FETCH c_employee into c_id, c_name, c_address;
EXIT when c_employee%notfound;
dbms_output.put_line(c_id||' '||c_name||' '||c_address);
END LOOP;
close c_employee;
end;
/
When I run this from SQLPlus I get only the details of the first row but not the rest. What am I doing wrong? How to get all the outputs for the loop.
Try to convert your code to use a for loop instead of the open statement, like so -
for r_employee in c_employee
LOOP
dbms_output.put_line(r_employee.c_id||' '||r_employee.c_name||' '||r_employee.c_address);
END LOOP;
Where r_employee is a variable of employee%type.
The way you currently wrote it does not iterate through the cursor, and this is why only the first row is presented.
Even though your code looks correct, it should iterate through all the
row not just one. Try to use below snippet and run it in SQL plus if
still single row then there may be some other issue.
SET SERVEROUTPUT ON
DECLARE
BEGIN
FOR I IN
(SELECT id, name, address FROM employee
)
LOOP
dbms_output.put_line(I.ID||' '||I.name||' '||I.address);
END LOOP;
END;
/

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

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

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;

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