I have written a package :
CREATE OR REPLACE
PACKAGE BODY NEW_HIRE_PKG
AS
PROCEDURE load_emp(
errbuf OUT VARCHAR2,
retcode OUT VARCHAR2 )
AS
CURSOR cur_person_info
IS
SELECT * FROM table_abc;
CURSOR cur_person_adr
IS
SELECT * FROM table_adr;
l_person_id NUMBER;
l_emp_num NUMBER;
lv_add_type VARCHAR2(100);
lv_address_line1 VARCHAR2(100);
BEGIN
FOR person_info_rec IN cur_address_info
LOOP
hr_employee_api.create_employee ( p_validate => FALSE,
--INPUT Parameter
P_HIRE_DATE =>person_info_rec.DATE_START,
-- output
p_employee_number => lc_employee_number, p_person_id => ln_person_id );
END LOOP ;
END;
PROCEDURE load_add(
errbuf OUT VARCHAR2,
retcode OUT VARCHAR2 )
as
ln_person_id number;
BEGIN
FOR address_info_rec IN cur_address_info
LOOP
BEGIN
hr_person_address_api.create_person_address
(p_validate => FALSE,
p_effective_date => TRUNC(SYSDATE),
p_person_id=> ln_person_id,
--output
p_address_type => lv_add_type,
p_address_line1 => lv_address_line1);
end;
end loop;
end;
end;
Now in the procedure the load_add there is a variable ln_person_id which should be the person ids generated in the procedure load_emp. I want to pass it in this procedure one by one. Can i do it by making ln_person_id an object ?
Judging by your code you have two concurrent programs - one that calls load_emp() and one that calls load_add(). If that's really the structure you want then the two calls will run in separate sessions and there's nothing you can do to pass a variable from one to the other. The best you could do would be to hold all the person_id values from load_emp in a custom table. The data could then later be consumed by load_add().
However I would restructure your package. Why not call load_add() from within the LOOP in load_emp() ?
Related
i am trying to call a function from stored procedure in Oracle, but not getting any idea how to do.
my function has two IN parameter and one OUT parameter.
in my procedure i am using out sys refcursor . Any refrence or example will help me a lot.
Here is a simple example for calling function inside procedure. Also as mentioned by APC using OUT in function is a bad practice. Instead you can return your required output. And I'm not sure how you are using sys_refcursor, so modify your procedure accordingly
CREATE OR REPLACE FUNCTION SUM_OF_2(NUM1 IN NUMBER,NUM2 IN NUMBER) RETURN NUMBER
IS
RESULT_SUM NUMBER;
BEGIN
RESULT_SUM:=NUM1+NUM2;
RETURN RESULT_SUM;
END;
CREATE OR REPLACE PROCEDURE CALL_FUNCTON(NUM1 NUMBER,NUM2 NUMBER)
AS
V_FINAL_RESULT NUMBER;
BEGIN
V_FINAL_RESULT:=SUM_OF_2(NUM1,NUM2);
DBMS_OUTPUT.PUT_LINE(V_FINAL_RESULT);
END;
BEGIN
CALL_FUNCTON(5,10);
END;
/
CHECK DEMO HERE
Not sure on what your requirement is , maybe you are just trying the code for education purposes. Generally I have not seen much code which uses OUT parameter with functions, in case you want to return multiple values to the caller object then you could use a procedure with more then one OUT variables. There are some limitation on how an oracle function with OUT parameter would differ from a normal function.
CREATE OR REPLACE FUNCTION temp_demo_func(out_var1 OUT NUMBER)
RETURN VARCHAR2 IS
BEGIN
out_var1 := 1;
RETURN 'T';
EXCEPTION
WHEN OTHERS THEN
RETURN 'F';
END temp_demo_func;
/
CREATE OR REPLACE PROCEDURE temp_demo_proc
(
in_var1 NUMBER
,cur_refcur_out OUT SYS_REFCURSOR
) IS
res VARCHAR2(1);
out_var1 NUMBER;
BEGIN
res := temp_demo_func(out_var1 => out_var1);
dbms_output.put_line(out_var1);
OPEN cur_refcur_out FOR
SELECT in_var1
,out_var1
,res
FROM dual;
END;
/
set serveroutput on
declare
cur_refcur_out Sys_Refcursor;
in_var1 number := 22;
begin
temp_demo_proc(in_var1 => in_var1
,cur_refcur_out => cur_refcur_out);
end;
/
I have three tables: test_main (could be empty on start), test_sec (almost always has records) and binding table test_ref(storess unique id combinations of records from test_main and test_sec).
I need to create a package with procedures that deal with inserions and updates of records in test_main and test_ref. I need some help with it.
Here's the code of a package:
create or replace package TEST_PKG is
type t_num is table of number;
procedure ADD (arg_main_id number
, arg_name varchar2
, arg_sec_ids t_num);
end test_pkg;
create or replace package body test_pkg is
procedure ADD (arg_main_id number
, arg_name varchar2
, arg_sec_ids t_num)
is begin
insert into test_main (id, col_name)
values (arg_main_id, arg_name);
commit;
for i in arg_sec_ids.first .. arg_sec_ids.last loop
insert into test_ref (main_id, sec_id)
values (arg_main_id, arg_sec_ids(i));
end loop;
commit;
end ADD;
end test_pkg;
I plan to call this procedure in Oracle APEX 5.1 PL/SQL Dynamic Action as follows:
declare
selection apex_t_number
-- or "test_pkg.t_num" with values from "apex_string.split_numbers" added through a "for" loop later
begin
selection := apex_string.split_numbers(:P1_SELECT2,':');
-- for example, '1:2:3' string results in a [1,2,3] array
ADD (arg_main_id => :P1_MAIN_ID
, arg_name => :P1_MAIN_NAME
, arg_sec_ids => selection);
end;
But I also would like to be able to call it as ADD (arg_main_id => :P1_MAIN_ID, arg_name => :P1_MAIN_NAME) with a default value for arg_sec_ids.
So, is it possible to define default value for a collection in PL/SQL Procedure, and if so, how to?
You can define arg_sec_ids parameter as of in out style is of type t_num.
create or replace package test_pkg is
type t_num is table of number;
procedure add (
arg_main_id number,
arg_name varchar2,
arg_sec_ids in out t_num
);
end;
and suppose to initialize with arg_sec_ids := t_num(1,1,2,3,5,8); in the program body, and if you extend with an integer with value number of elements in the tuple, you can use the next values for arg_sec_ids such as arg_sec_ids(7),..,arg_sec_ids(10).
create or replace package body test_pkg is
procedure add (
arg_main_id number,
arg_name varchar2,
arg_sec_ids in out t_num
) is
begin
arg_sec_ids := t_num(1,1,2,3,5,8);
arg_sec_ids.extend(10);
insert into test_main (id, col_name)
values (arg_main_id, arg_name);
for i in arg_sec_ids.first .. arg_sec_ids.last loop
insert into test_ref (main_id, sec_id)
values (arg_main_id, arg_sec_ids(i));
end loop;
arg_sec_ids(7) := arg_sec_ids(5)+ arg_sec_ids(6);
dbms_output.put_line( ' arg_sec_ids(7)''s values is : '||arg_sec_ids(7) );
commit;
end add;
end;
If arg_sec_ids.extend(x) is omitted (where x>6 ), it's impossible to use arrays with index more than default length( which's 6 in this case ).
I have created a package xyz like follows :-
create or replace package xyz
is
procedure abc( v_frst_param in VARCHAR2 default 'Y')
IS
BEGIN
dbms_output.put_line(v_frst_param);
-- CALLING another function
update_table(p_frst_parm =>v_frst_param,
p_second_param =>'2');
END;
In the dbms_output.put_line the output is coming null when i am not passing any value while calling abc procedure.
if i have passed default and i am not passign any parameter shouldnt the value come as Y in the ouput
First of all, I think that package would be invalid, you are trying to add a body for your function in your package specification. However the whole idea is good and it should be working, if done right, for example, create a package:
create or replace package xyz is
procedure abc(v_frst_param in varchar2 default 'Y');
procedure abc(v_frst_param in varchar2 default 'Y', v_second_param in varchar2);
end xyz;
And a package body:
create or replace package body xyz is
procedure abc(v_frst_param in varchar2 default 'Y') is
begin
dbms_output.put_line(v_frst_param);
end;
procedure abc(v_frst_param in varchar2 default 'Y', v_second_param in varchar2) is
begin
dbms_output.put_line(v_frst_param || ' / ' || v_second_param);
end;
end xyz;
Then you may want to make the call of your procedure:
begin
xyz.abc;
xyz.abc(); -- This is the same thing as above
xyz.abc(v_second_param => 'Maybe');
end;
Please note that if you send anything as a parameter for v_first_parameter to that procedure, it will use the value you sent and not the default one.
Try this out
Mostly depends on how you are calling your procedure -ABC(); or ABC; or ABC(NULL); or ABC(''); and the way your parameters are declared.
Create or replace procedure ABC(v_frst_param IN VARCHAR2 Default 'Y')
AS
OUT_v_frst_param VARCHAR2(100);
BEGIN
OUT_v_frst_param := v_frst_param ;
dbms_output.put_line('The PROCEDURE OUTPUT is : ' || OUT_v_frst_param );
END;
--Procedure created.
BEGIN
ABC(); --calling procedure
END;
The PROCEDURE OUTPUT is : Y
Statement processed.
Now if you call your procedure like:
BEGIN
ABC; --calling procedure
END;
The PROCEDURE OUTPUT is : Y
Statement processed.
--passing `NULL`
BEGIN
ABC(NULL);
END;
The PROCEDURE OUTPUT is :
Statement processed.
-- Passing again ''
BEGIN
ABC('');
END;
The PROCEDURE OUTPUT is :
Statement processed.
--passing text
BEGIN
ABC('hello world');
END;
The PROCEDURE OUTPUT is : hello world
Statement processed.
I am totally new to PL/SQL.
create or replace procedure p1(a in customer.id%type,
b out customer.name%type,
c out customer.dept%type)
is
begin
select name,dept into b,c from customer where id=a;
end;
Its created properly.
But I am not sure how to execute it.
EXEC p1(1);
But this is showing error.
Your procedure has three parameters so you'd need to call it with three parameters. In the case of OUT parameters, you need to pass in variables that will hold the values that are being returned by the procedure.
DECLARE
l_id customer.id%type := 1;
l_name customer.name%type;
l_dept customer.dept%type;
BEGIN
p1( l_id, l_name, l_dept );
<<do something with l_name and l_dept>>
END;
/
There are two ways to execute a procedure.
From the SQL prompt.
EXECUTE [or EXEC] procedure_name;
Within another procedure – simply use the procedure name.
procedure_name;
the procedure have 3 parameters, you can't call it like p1(1) using just one parameter
in your case try something like this
DECLARE
p_name customer.name%type;
p_department customer.dept%type;
BEGIN
p1(1, p_name, p_department);
END;
Output parameters should be stored in variables.
Input, can be variables or directly given in between the ( )
Use dbms_output.put_line to easily show output in your IDE.
DECLARE
p_name customer.name%type;
p_department customer.dept%type;
p_id customer.id%type := 1;
BEGIN
p1(p_id, p_name, p_department);
END;
I am trying to use a GET stored procedure/cursor to show the GAME NAME of a Lottery Game Table I created in a lottery game database.
Here is the code:
CREATE OR REPLACE PROCEDURE GetLotteryGameName (
p_lgid IN NUMBER,
p_value out VARCHAR2,
p_field IN VARCHAR2
)
IS
BEGIN
SELECT GAMENAME
INTO p_value
FROM LOTTERYGAME
WHERE LOTTERYGAMEID = p_lgid;
END GetLotteryGameName;
CREATE OR REPLACE PACKAGE GETLOTTERYGAMENAMEPKG IS
PROCEDURE GetLotteryGameName (
p_lgid IN NUMBER,
p_value out VARCHAR2,
p_field IN VARCHAR2
);
TYPE per_ref_cursor IS REF CURSOR;
PROCEDURE GetGameName (p_lgid IN NUMBER, p_ref OUT per_ref_cursor);
END GETLOTTERYGAMENAMEPKG;
CREATE OR REPLACE PACKAGE BODY GETLOTTERYGAMENAMEPKG IS
PROCEDURE GetLotteryGameName (
p_lgid IN NUMBER,
p_value out VARCHAR2,
p_field IN VARCHAR2
)
IS
BEGIN
SELECT GAMENAME
INTO p_value
FROM LOTTERYGAME
WHERE LOTTERYGAMEID = p_lgid;
END GetLotteryGameName;
PROCEDURE GetName
(p_lgid IN NUMBER,
p_ref OUT per_ref_cursor) IS
BEGIN
OPEN p_ref FOR
SELECT GAMENAME
FROM LOTTERYGAME
WHERE LOTTERYGAMEID = p_lgid;
END GetName;
END GETLOTTERYGAMENAMEPKG;
DECLARE
v_cursor GETLOTTERYGAMENAMEPKG.per_ref_cursor;
v_lgid LOTTERYGAME.LOTTERYGAMEID%TYPE;
v_gamename LOTTERYGAME.GAMENAME%TYPE;
BEGIN
GETLOTTERYGAMENAMEPKG.GetName (p_lgid = 2,
p_ref => v_cursor);
LOOP
FETCH v_cursor
INTO v_lgid, v_gamename;
EXIT WHEN v_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_lgid || ',' || v_gamename);
END LOOP;
CLOSE v_cursor;
END;
When I run the above declare statement, I get the following error:
06504. 00000 - "PL/SQL: Return types of Result Set variables or query do not match"
*Cause: Number and/or types of columns in a query does not match declared
return type of a result set variable, or declared types of two Result
Set variables do not match.
I know there is an error somewhere in this code, I just don't know what I'm looking for, or how to set myself up to avoid future failures like this.
Any help is much appreciated,
Cheers,
FBF
As the error says, you SELECT only GAMENAME in your SELECT but attempt to put into v_lgid, v_gamename.
So adding LOTTERYGAMEID to your CURSOR's SELECT
Or Change your anonymous block.
PROCEDURE GetName
(p_lgid IN NUMBER,
p_ref OUT per_ref_cursor) IS
BEGIN
OPEN p_ref FOR
SELECT GAMENAME,LOTTERYGAMEID
FROM LOTTERYGAME
WHERE LOTTERYGAMEID = p_lgid;
END GetName;
You should also correct the syntax error in:
GETLOTTERYGAMENAMEPKG.GetName (p_lgid = 2,
p_ref => v_cursor);
which should read
GETLOTTERYGAMENAMEPKG.GetName (p_lgid => 2,
p_ref => v_cursor);
Share and enjoy.