[PL/SQL]how to make a loop that runs multiple procedures - sql

suppose I have a list of procedures p1,p2,p3..pn , each procedure has only one output number parameter, basically each procedure is a constant number. How could I create a loop that runs all these procedures and the results are displayed on the screen? I tried with EXECUTE IMMEDIATE something like:
DECLARE
i number;
n number:=5;
print number;
begin
for i in 1 .. n loop
EXECUTE IMMEDIATE 'BEGIN p'||i||'('||print||') END;' ;
dbms_output.put_line(print);
end loop;
end;
I also tried the form [EXECUTE IMMEDIATE sql_stmt INTO print USING i]
but I still haven't done anything

It's BEGIN myprocedure; END; - you're missing the ";" after the procedure call. It's unclear what you want the "print" to do, that is not declared anywhere so it will just print an empty value.
CREATE OR REPLACE procedure p1
AS
BEGIN
dbms_output.put_line('this is 1');
END;
/
CREATE OR REPLACE procedure p2
AS
BEGIN
dbms_output.put_line('this is 2');
END;
/
DECLARE
n number:=2;
begin
for i in 1 .. n loop
EXECUTE IMMEDIATE 'BEGIN p'||i||'; END;' ;
end loop;
end;
/
this is 1
this is 2

Related

run a procedure in while loop

I have this stored proc :
begin
Sp_Racf_Test;
end;
I don't want to edit anything inside this proc.
I want to run a loop statement where it should run the proc Sp_Racf_Test until
a column RACF_ID in table tem_joins is null. I mean the loop of running stored procedure should stop when there are no null values in the column RACF_ID of table tem_joins.
Please suggest a query
Try the below one:
declare
v_count number := 1;
begin
while v_count > 0 loop
Select count(*) into v_count from tem_joins
where racf_id is null;
if v_count > 0 then
Sp_Racf_Test;
else
exit;
end if;
end loop;
end;

EXECUTE IMMEDIATE PL/SQL Block return type

As part of a test I want to run a PL/SQL block using EXECUTE IMMEDIATE but when I try to fetch the result with INTO it always returns the same error regardless the content of the PL/SQL block I want to run.
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN COMMIT; END;' INTO l_output;
END;
/
And the error is
ORA-01007: variable not in select list
I know this error has to with l_output not being the same type as the returning type by EXECUTE IMMEDIATE, but I don't know the type. I already tried to change l_output to CLOB, BLOB, NUMBER and nothing changes. Any idea?
OK, this is another example, same result.
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN DBMS_OUTPUT.PUT_LINE(''TEST''); END;' INTO l_output;
END;
/
Oracle is complaining because your PL/SQL does not return anything for it to store in l_output. What are you expecting the value of l_output to be?
One would use EXECUTE IMMEDIATE...INTO with something like this to return a value from a PL/SQL block.
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'SELECT ''ABC'' FROM DUAL' INTO l_output;
dbms_output.put_line('l_output = ' || l_output);
END;
/
UPDATE
If you want, you can do this:
DECLARE
l_output VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'BEGIN :1 := 5; END;' USING IN OUT l_output;
dbms_output.put_line('l_output = ' || l_output);
END;

Create stored procedure which returns in one OUT param database version (Oracle)

I new with PL\SQL so i'm traying to make a procedure witch return database version with OUT in one param. My SQL code is:
CREATE OR REPLACE PROCEDURE getVersion(outParam1 OUT VARCHAR2)
IS
BEGIN
outParam1 := SELECT * FROM V$VERSION;
END;
Can some one explain me how to write procedure right way and how to execute the procedure.
Try as
CREATE OR REPLACE PROCEDURE getVersion (out_cursor OUT SYS_REFCURSOR)
AS
BEGIN
OPEN out_cursor FOR SELECT * FROM V$VERSION;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (SQLERRM);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM);
END getVersion;
In order to execute from SQL Plus, do as
VARIABLE mycursor REFCURSOR;
BEGIN
getVersion (:mycursor);
END;
/
PRINT mycursor
From SQL Developer do as
var mycursor refcursor
exec getVersion(:mycursor)
print mycursor
If you would like to have OUT varchar2 with a single row, then you could something like
CREATE OR REPLACE PROCEDURE myProc (outParam1 OUT VARCHAR2)
AS
BEGIN
SELECT dummy INTO outParam1 FROM DUAL;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (SQLERRM);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM);
END myProc;
and execute as
VARIABLE testvar VARCHAR2(16);
EXEC myProc(:testvar);
PRINT testvar;

Dynamic SQL LOOP

Dynamic SQL is not my friend, basically the idea is that I can use the procedure with the "p_in_table" paramter to get the number of rows contained in the table.
CREATE OR REPLACE PROCEDURE how_many_rows(p_in_table VARCHAR2)
IS
TYPE cur_cur IS REF CURSOR;
v_cur_cur cur_cur;
v_rowcount NUMBER(28);
v_cur_txt VARCHAR2(299);
BEGIN
v_cur_txt := 'SELECT * FROM ' || p_in_table;
OPEN v_cur_cur FOR v_cur_txt;
LOOP
v_rowcount := v_cur_cur%ROWCOUNT;
EXIT WHEN v_cur_cur%NOTFOUND;
END LOOP;
CLOSE v_cur_cur;
dbms_output.put_line(v_rowcount);
END;
Would preciate it if someone would tell me what am I doing wrong?
The problem is that you not iterating through cursor - no fetch statement or something like that, so, basically, you have an infinite loop. To avoid this you need to do something like this:
CREATE OR REPLACE PROCEDURE how_many_rows
(p_in_table VARCHAR2) IS
TYPE cur_cur IS REF CURSOR;
v_cur_cur cur_cur;
v_rowcount NUMBER(28);
v_cur_txt VARCHAR2(299);
v_row SOME_TABLE%ROWTYPE; --add row variable
BEGIN
v_cur_txt := 'SELECT * FROM '|| p_in_table;
OPEN v_cur_cur FOR v_cur_txt;
LOOP
v_rowcount := v_cur_cur%ROWCOUNT;
FETCH v_cur_cur INTO v_row; --fetch a row in it
EXIT WHEN v_cur_cur%NOTFOUND;
END LOOP;
CLOSE v_cur_cur;
DBMS_OUTPUT.PUT_LINE(v_rowcount);
END;
But, as you can see, to do this you need to know, what table you're quering, so this is not general solution. Maybe there is a workaround for this, but i suggest, you use more simple and efficient approach, for example with EXECUTE IMMEDIATE:
CREATE OR REPLACE PROCEDURE HOW_MANY_ROWS(p_in_table VARCHAR2)
IS
v_tmp NUMBER;
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM ' || p_in_table INTO v_tmp;
DBMS_OUTPUT.PUT_LINE(v_tmp);
END;
Ok, I gave a thought on how to achieve this using your way, and here is what i've ended up with - just fetch ROWNUM from your table, every table has it and you know it's type - NUMBER. So this procedure will work in general case:
CREATE OR REPLACE PROCEDURE how_many_rows
(p_in_table VARCHAR2) IS
TYPE cur_cur IS REF CURSOR;
v_cur_cur cur_cur;
v_rowcount NUMBER(28);
v_cur_txt VARCHAR2(299);
v_row NUMBER; --add rownum variable
BEGIN
v_cur_txt := 'SELECT ROWNUM FROM '|| p_in_table; --select only rownum from target table
OPEN v_cur_cur FOR v_cur_txt;
LOOP
v_rowcount := v_cur_cur%ROWCOUNT;
FETCH v_cur_cur INTO v_row; --fetch rownum in it
EXIT WHEN v_cur_cur%NOTFOUND;
END LOOP;
CLOSE v_cur_cur;
DBMS_OUTPUT.PUT_LINE(v_rowcount);
END;

returning into clause with dynamic sql

I have copied and pasted this from http://www.oracle-base.com/articles/misc/dml-returning-into-clause.php
But this code goes on and on while executing ...
SET SERVEROUTPUT ON
DECLARE
TYPE t_tab IS TABLE OF t1.id%TYPE;
l_tab t_tab;
BEGIN
EXECUTE IMMEDIATE 'UPDATE t1
SET description =' ||'description '||'
RETURNING id INTO :l_tab'
RETURNING BULK COLLECT INTO l_tab;
FOR i IN l_tab.first .. l_tab.last LOOP
DBMS_OUTPUT.put_line('UPDATE ID=' || l_tab(i));
END LOOP;
COMMIT;
END;
Any mistypes or errors in the code ?
You have to add a / at the end of the PL/SQL block to execute it.