How to call a stored procedure from sqlplus?
I have a procedure:
Create or replace procedure testproc(parameter1 in varachar2,parameter2 out varchar2)
begin
Do something
end;
I tried exec testproc(12,89) ::Returns error
The second parameter of your procedure is an OUT parameter -- its value will be assigned to the variable passed when the procedure completes. So you can't use a literal value for this parameter.
You can declare a bind variable at the SQLPlus prompt and use that:
-- Declare bind variable
VARIABLE x NUMBER
-- If necessary, initialize the value of x; in your example this should be unnecessary
-- since the value of the second parameter is never read
EXEC :x := 1
-- Call the procedure
EXEC testproc(12, :x)
-- Print the value assigned to the bind variable
PRINT x
Alternatively, you can use an anonymous PL/SQL block:
-- Activate client processing of dbms_output buffer
SET SERVEROUTPUT ON
-- In anonymous block, declare variable, call procedure, print resulting value
DECLARE
x NUMBER;
BEGIN
testproc(12, x);
dbms_output.put_line( x );
END;
/
create or replace procedure autogenerate(t1 in int,t2 in int)
is
jum number;
begin
if t1 < 10 then
dbms_output.put_line('Value too low.');
else if t1 > 20 then
dbms_output.put_line('Value too high.');
end if;
end if;
end;
/
show errors;
set serveroutput on;
execute autogenerate(1,2);
Try this, if you have question just post it again to me :)
Related
I need to test a package procedure which accepts a PL/SQL table and returns SYS_REFCURSOR.
What I am looking for is Anonymous PL/SQL block which does the following :
populates PL/SQL table and pass to procedure
The relevant code is below:
create or replace type rec_typ as object
(
fname varchar2(10),
lname varchar2(10)
)
/
create or replace type rec_arr as table of rec_typ
/
create or replace package get_emp_pkg
as
procedure get_emp
(
l_rec rec_arr,
p_out out sys_refcursor
);
end;
/
create or replace package body get_emp_pkg
as
procedure get_emp
(
l_rec rec_arr,
p_out out sys_refcursor
)
as
l_out rec_arr;
begin
open p_out for select * from table ( l_out );
end;
end;
/
You need to declare and populate a table collection, and declare a cursor variable; and then pass those into the procedure call; e.g.:
declare
l_rec rec_arr;
l_cur sys_refcursor;
begin
l_rec := rec_arr(rec_typ('Joe','Bloggs'), rec_typ('Mary','Berry'));
get_emp_pkg.get_emp(l_rec, l_cur);
-- do something with the cursor
close l_cur;
end;
/
If you are just testing it and you're using SQL*Plus or SQL Developer you could simplify this to use a client bind variable:
variable cur refcursor;
declare
l_rec rec_arr;
begin
l_rec := rec_arr(rec_typ('Joe','Bloggs'), rec_typ('Mary','Berry'));
get_emp_pkg.get_emp(l_rec, :cur);
end;
/
print cur;
or even more simply:
variable cur refcursor;
begin
get_emp_pkg.get_emp(rec_arr(rec_typ('Joe','Bloggs'), rec_typ('Mary','Berry')), :cur);
end;
/
print cur;
and you could even replace that with an execute call, which is just a wrapper for an anonymous block anyway, so functionally almost identical.
Your procedure has a mistake though; you're declaring a local l_out variable and then opening the ref cursor based on that, but you don't ever populate it - so the ref cursor result set will always be empty. If you change it to use l_rec instead (though I would call that p_rec, with the p_ prefix indicating a parameters and leave the l_ prefix for local variables):
create or replace package body get_emp_pkg
as
procedure get_emp
(
l_rec rec_arr,
p_out out sys_refcursor
)
as
begin
open p_out for select * from table ( l_rec );
end get_emp;
end;
/
then the bind variable versions above both see:
PL/SQL procedure successfully completed.
FNAME LNAME
---------- ----------
Joe Bloggs
Mary Berry
I am using SQLDEVELOPER TO make a stored procedure. this is my procedure
create or replace PROCEDURE SPP
(
inpt IN VARCHAR2,
opt OUT VARCHAR2
)
AS
BEGIN
SELECT U_ID
INTO opt
FROM TABLE_NAME
WHERE U_ID=inpt;
END;
so it should return the value in opt which i can then print or whatever.
i dont know how to execute it i tried running this script
var opt VARCHAR2;
exec SPP('test_user') := opt
but it doesnt work this is my first time doing stored procs and I'm really confused any help is appreciated
how do i make it run? i can make a stored proc run with input variables but with an output variable i mess up and I cant do it without using the SELECT (item) INTO format.
In order to call the procedure, you'd need to pass in a variable that the procedure can populate. Something like
DECLARE
l_output table_name.u_id%type;
BEGIN
spp( 'test_user', l_output );
END;
Now, that being said, declaring a stored procedure whose only purpose is to query the database and return a value is generally the wrong architectural choice. That's why functions exist.
CREATE OR REPLACE FUNCTION some_function( p_input IN table_name.u_id%type )
RETURN table_name.u_id%type
IS
l_uid table_name.u_id%type;
BEGIN
SELECT u_id
INTO l_uid
FROM table_name
WHERE u_id = p_input;
RETURN l_uid;
END;
which you can then call either in a PL/SQL block
DECLARE
l_output table_name.u_id%type;
BEGIN
l_output := some_function( 'test_user' );
END;
or in a SQL statement
SELECT some_function( 'test_user' )
FROM dual;
I have the following table and relevant column..
TABLEA
SQL_SCRIPT CLOB
Here is a procedure that executes the pl/sql block in the clob..
Create procedure (p_exit_code IN OUT NUMBER)
AS
V_sql_val sql_script%TYPE;
…
BEGIN
Select sql_script into v_sql_val from tablea;
EXECUTE IMMEDIATE sql_script;
END;
In SQL_SCRIPT I am trying to do following in the exception handler:
EXCEPTION
WHEN EXCP_STOP_PROCESS THEN
p_exit_code := 1;
END;
I need to set the value of p_exit_code parameter in procedure from the clob script. How can I do this?
If I understand correctly, you need to set the value of a variable within sql_script and return this to the calling procedure. This can be achieved using bind variables. A very simple test case is below:
declare
-- ':return_code' is the bind variable
sql_script varchar2(1000) := 'begin :return_code := 1; end;';
vn_result number;
begin
execute immediate sql_script using out vn_result;
dbms_output.put_line(vn_result);
end;
my procedure looks like this:
create or replace procedure odcitaj_surovinu_zo_skladu
(
v_id_suroviny IN surovina.id_suroviny%TYPE,
odcitaj IN OUT number
)
as
begin
...//some code here
odcitaj:=odcitaj-22;
...//some code here
end;
Procedure compiled w/o errors. I'm trying to execute it as:
execute odcitaj_surovinu_zo_skladu(1,200);
But it gives error, that '200' can't be used as target of assigment.
So how to execute it? Does ODCITAJ even need to be IN OUT? Cause i know that, if it was just IN , then it would act as constant and i won't be able to assign it anything
As Dmitry Bychenko said, you have to use a variable as the target of an OUT or IN OUT parameter, you can't provide a constant. Your parameter does need to be IN OUT since you're modifying it in the procedure. You can either use an anonymous block:
declare
l_odcitaj number;
begin
l_odcitaj := 200;
odcitaj_surovinu_zo_skladu(1, l_odcitaj);
-- do something with the updated value of l_odcitaj
end;
/
If you want to use the SQL*Plus/SQL Developer execute shorthand wrapper for an anonymous block you can declare a bind variable instead:
variable l_odcitaj number;
exec :l_odcitaj := 200;
exec odcitaj_surovinu_zo_skladu(1, :l_odcitaj);
Notice that the variable name has a colon in front when it is set and when the procedure is called, because it is a bind variable.
If you want you can then use that updated bind variable in other calls, or print it's post-procedure value:
print l_odcitaj
If the updated value - from odcitaj:=odcitaj-22; - doesn't need to be returned and is only used inside the procedure, you could declare the argument as IN and have a local variable which you set from the argument and then manipulate and use in the procedure.
create or replace procedure odcitaj_surovinu_zo_skladu
(
v_id_suroviny IN surovina.id_suroviny%TYPE,
v_odcitaj IN number
)
as
l_odcitaj number;
begin
l_odcitaj := v_odcitaj;
...//some code here
l_odcitaj:=l_odcitaj-22;
...//some code here
end;
/
You could then call the procedure with constant values. It just depends whether the caller needs to know the modified value.
Does anyone know of a way, or even if its possible, to call a stored procedure from within another? If so, how would you do it?
Here is my test code:
SET SERVEROUTPUT ON;
DROP PROCEDURE test_sp_1;
DROP PROCEDURE test_sp;
CREATE PROCEDURE test_sp
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Test works');
END;
/
CREATE PROCEDURE test_sp_1
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Testing');
test_sp;
END;
/
CALL test_sp_1;
Your stored procedures work as coded. The problem is with the last line, it is unable to invoke either of your stored procedures.
Three choices in SQL*Plus are: call, exec, and an anoymous PL/SQL block.
call appears to be a SQL keyword, and is documented in the SQL Reference. http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_4008.htm#BABDEHHG The syntax diagram indicates that parentesis are required, even when no arguments are passed to the call routine.
CALL test_sp_1();
An anonymous PL/SQL block is PL/SQL that is not inside a named procedure, function, trigger, etc. It can be used to call your procedure.
BEGIN
test_sp_1;
END;
/
Exec is a SQL*Plus command that is a shortcut for the above anonymous block. EXEC <procedure_name> will be passed to the DB server as BEGIN <procedure_name>; END;
Full example:
SQL> SET SERVEROUTPUT ON
SQL> CREATE OR REPLACE PROCEDURE test_sp
2 AS
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE('Test works');
5 END;
6 /
Procedure created.
SQL> CREATE OR REPLACE PROCEDURE test_sp_1
2 AS
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE('Testing');
5 test_sp;
6 END;
7 /
Procedure created.
SQL> CALL test_sp_1();
Testing
Test works
Call completed.
SQL> exec test_sp_1
Testing
Test works
PL/SQL procedure successfully completed.
SQL> begin
2 test_sp_1;
3 end;
4 /
Testing
Test works
PL/SQL procedure successfully completed.
SQL>
Sure, you just call it from within the SP, there's no special syntax.
Ex:
PROCEDURE some_sp
AS
BEGIN
some_other_sp('parm1', 10, 20.42);
END;
If the procedure is in a different schema than the one the executing procedure is in, you need to prefix it with schema name.
PROCEDURE some_sp
AS
BEGIN
other_schema.some_other_sp('parm1', 10, 20.42);
END;
#Michael Lockwood - you don't need to use the keyword "CALL" anywhere. You just need to mention the procedure call directly.
That is
Begin
proc1(input1, input2);
end;
/
instead of
Begin
call proc1(input1, input2);
end;
/
To invoke the procedure from the SQLPlus command line, try one of these:
CALL test_sp_1();
EXEC test_sp_1
Calling one procedure from another procedure:
One for a normal procedure:
CREATE OR REPLACE SP_1() AS
BEGIN
/* BODY */
END SP_1;
Calling procedure SP_1 from SP_2:
CREATE OR REPLACE SP_2() AS
BEGIN
/* CALL PROCEDURE SP_1 */
SP_1();
END SP_2;
Call a procedure with REFCURSOR or output cursor:
CREATE OR REPLACE SP_1
(
oCurSp1 OUT SYS_REFCURSOR
) AS
BEGIN
/*BODY */
END SP_1;
Call the procedure SP_1 which will return the REFCURSOR as an output parameter
CREATE OR REPLACE SP_2
(
oCurSp2 OUT SYS_REFCURSOR
) AS `enter code here`
BEGIN
/* CALL PROCEDURE SP_1 WITH REF CURSOR AS OUTPUT PARAMETER */
SP_1(oCurSp2);
END SP_2;