Procedure to input number and output varchar2 - oracle

I need to write a procedure to input let's say a rep_id and then output the rep_name that corresponds to the rep_id.
After that, I need to use another procedure to call the above procedure.
Here is what I have for the first procedure.
create or replace procedure p_inout
(v_rep_id in number)
As
v_first_name varchar2(20);
v_last_name varchar2(20);
begin
select first_name,last_name into v_first_name, v_last_name
from rep
where rep_id = v_rep_id;
dbms_output.put_line(v_first_name||' '||v_last_name);
end p_inout;
/
Execute p_inout(100);
And here is my procedure to call the above procedure
create or replace procedure p_call
is
v_first_name varchar2(20);
v_last_name varchar2(20);
begin
p_inout(100);
dbms_output.put_line(v_first_name||' '||v_last_name);
end p_call;
/
execute p_call
I was able to get the result but one guy told me that my call procedure should be like this
Create or replace procedure p_call
Is
V_name varchar2(20);
Begin
P_inout(100,v_name); --100 is a rep id
Dbms_output.Put_line(v_name);
End;
/
Execute p_call
Doesn't my procedure to call and his call procedure produce the same result?

CREATE TABLE minions (
rep_id DATE CONSTRAINT minions__rep_id__pk PRIMARY KEY,
rep_name NUMBER CONSTRAINT minions__rep_name__nn NOT NULL
CONSTRAINT minions__rep_name__u UNIQUE
)
/
CREATE OR REPLACE PROCEDURE myCatWasSick (
p_rep_id IN minions.rep_id%TYPE,
p_rep_name OUT minions.rep_name%TYPE
)
IS
BEGIN
SELECT rep_name
INTO p_rep_name
FROM minions
WHERE rep_id = p_rep_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_rep_name := NULL;
END myCatWasSick;
/
CREATE OR REPLACE PROCEDURE releaseTheBadgers
IS
the_badger NUMBER(10);
BEGIN
myCatWasSick( SYSDATE + 1, the_badger );
// Do something with the_badger.
END releaseTheBadgers;
/

Related

stored procedure compiled with errors

I have a stored procedure where I am trying to take 2 input age and name
That will update the record in employee table.
But when I am compiling getting - compiled with errors
Code :
CREATE OR REPLACE PROCEDURE update_emp_age
(
v_age in number;
v_ename in varchar2(255 char);
) AS
BEGIN
UPDATE employee
SET
eage = v_age
WHERE
ename = v_ename;
ROLLBACK;
END;
Remove the size from the data types in the signature.
Use commas and not semi-colons between arguments in the signature.
Don't ROLLBACK (else your query will perform the update and then immediately ROLLBACK the change doing lots of work for no effect and potentially rolling back prior chages).
Like this:
CREATE OR REPLACE PROCEDURE update_emp_age
(
v_age in NUMBER,
v_ename in VARCHAR2
) AS
BEGIN
UPDATE employee
SET eage = v_age
WHERE ename = v_ename;
END;
/
You could also use %TYPE in the signature:
CREATE OR REPLACE PROCEDURE update_emp_age
(
v_age in EMPLOYEE.EAGE%TYPE,
v_ename in EMPLOYEE.ENAME%TYPE
) AS
BEGIN
UPDATE employee
SET eage = v_age
WHERE ename = v_ename;
END;
/
db<>fiddle here

Oracle PL/SQL - procedure with array parameter

I need to write an oracle procedure which will have an array of ID's as parameter.
Then I will return a cursor which contains result of select(1).
(1) - select * from table where id in(ID's)
As an option we can pass a string param and then convert string to array.
DECLARE
info sys_refcursor ;
error varchar(255);
BEGIN
package.test_function('1,2,3',info ,error);// info will contain a result cursor for select(1)
END;
Do you have other ideas?
You can create a user-defined collection type:
CREATE TYPE int8_list IS TABLE OF NUMBER(8,0);
Then your package:
CREATE PACKAGE pkg_name AS
PROCEDURE proc_name (
i_ids IN int8_list,
o_cursor OUT SYS_REFCURSOR
);
END;
/
CREATE PACKAGE BODY pkg_name AS
PROCEDURE proc_name (
i_ids IN int8_list,
o_cursor OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN o_cursor FOR
SELECT * FROM table_name WHERE id MEMBER OF i_ids;
END;
END;
/
Then you can call the procedure:
DECLARE
v_info sys_refcursor ;
v_id TABLE_NAME.ID%TYPE;
v_value TABLE_NAME.VALUE%TYPE;
BEGIN
pkg_name.proc_name(int8_list(1,2,3), v_info);
LOOP
FETCH v_info INTO v_id, v_value;
EXIT WHEN v_info%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_id || ' ' || v_value);
END LOOP;
END;
/
Which, for the sample data:
CREATE TABLE table_name (id, value) AS
SELECT LEVEL, CHR(64+LEVEL) FROM DUAL CONNECT BY LEVEL <= 5;
Outputs:
1 A
2 B
3 C
db<>fiddle here

Using count(*) to fetch more than one row in a SQL Procedure

I'm trying to return the number of rows per invoice_id using a function and procedure. Some invoice_id's have more than one row and I'm not sure how to fetch the count when I execute my procedure. As an example invoice_id(7) has just one row, but invoice_id(100) has four rows of information.
Create or replace function return_num_rows_function(invoice_id_text in varchar2)
Return varchar2
Is inv_id varchar2(20);
Begin
Select count(*)invoice_id into inv_id from invoice_line_items where invoice_id=invoice_id_text;
Return inv_id;
End;
Create or replace procedure return_num_rows (invoice_id_text in varchar2)
Is inv_id varchar(20);
line_item_desc invoice_line_items.line_item_description%type;
Begin
inv_id := return_num_rows_function(invoice_id_text);
If inv_id is not null then
Select count(*)invoice_id, line_item_description into inv_id,line_item_desc
From invoice_line_items where invoice_id = inv_id;
dbms_output.put_line('The number of rows returned:'|| inv_id);
dbms_output.put_line('Item description(s):'|| line_item_desc);
End if;
End;
set serveroutput on;
execute return_num_rows(7);
First of all do not use a string type variable for a numeric one
(invoice_id_text).
For your case it's better to use a procedure instead of called
function ( return_num_rows_function ), since you need two out
arguments returned.
A SQL Select statement cannot be used without Group By with aggegated and non-aggregated columns together ( i.e. don't use this one :
Select count(*) invoice_id, line_item_description
into inv_id,line_item_desc
From invoice_line_items
Where invoice_id = inv_id;
)
So, Try to create below procedures :
SQL> CREATE OR REPLACE Procedure
return_num_rows_proc(
i_invoice_id invoice_line_items.invoice_id%type,
inv_id out pls_integer,
line_item_desc out invoice_line_items.line_item_description%type
) Is
Begin
for c in
(
Select line_item_description
into line_item_desc
From invoice_line_items
Where invoice_id = i_invoice_id
)
loop
line_item_desc := line_item_desc||' '||c.line_item_description;
inv_id := nvl(inv_id,0) + 1;
end loop;
End;
/
SQL> CREATE OR REPLACE Procedure
return_num_rows(
i_invoice_id pls_integer
) Is
inv_id pls_integer;
line_item_desc invoice_line_items.line_item_description%type;
Begin
return_num_rows_proc(i_invoice_id,inv_id,line_item_desc);
If inv_id is not null then
dbms_output.put_line('The number of rows returned:' || inv_id);
dbms_output.put_line('Item description(s):' || line_item_desc);
End if;
End;
/
and call as in your case :
SQL> set serveroutput on;
SQL> execute return_num_rows(7);
Replace inv_id varchar2(20) with inv_id number;
and also if you want to get two outputs from procedure better to use refcursor.

Oracle Stored Procedure

My question is pretty basic but I am complete newbie to stored procedure and need to get around quickly. Any help will be appreciated,
Below is the current stored procedure we have,
PROCEDURE get_something(
type IN VARCHAR2,
value IN VARCHAR2,
i_type OUT VARCHAR2,
i_id OUT VARCHAR2)
AS
TYPE t_array
IS
TABLE OF VARCHAR2(320);
identifers t_array;
column_name VARCHAR2(32);
info_qry VARCHAR2(500);
top_row_qry VARCHAR2(500);
BEGIN
identifers := t_array('ABC');
column_name := get_column_name(type);
info_qry := 'select INS.i_id, INS.model from table1 INS where INS.'||column_name||'='''||value||''' order by INS.version desc';
top_row_qry := 'select * from ('||info_qry||') where rownum<=1';
EXECUTE immediate top_row_qry INTO i_id, i_type;
EXCEPTION
WHEN OTHERS THEN
i_id := NULL;
i_type := NULL;
END get_something;
Now when I execute this procedure, it gives me one record due to the rownum condition.
My requirement is to remove the rownum from the top_row_qry, so result would be multiple rows.
I want to store each field into some variable out of which I will use one of the variable for some comparison in the procedure itself.
So basically i want to store the results which I can later loop over and compare with a list of values.
Also, I need to define the list of values in this procedure itself.
Something like below:
list_of_vals:= t_array('ABC','XYZ');
Can anyone help me on this.
I guess you need to use cursor as OUT parameter for your procedure and later use it for your requirement.
Also for "I need to define the list of values in this procedure itself."
you can use a collection the way I have used in the procedure code (v_array).
You can then use a loop to traverse through multiple values for the v_array.
CREATE ORE REPLACE PROCEDURE get_something(type IN VARCHAR2,
value IN VARCHAR2,
out_param OUT sys_refcursor)
AS
TYPE t_array IS TABLE OF VARCHAR2(320);
v_array t_array:=t_array();
-- identifers t_array;
column_name VARCHAR2(32);
info_qry VARCHAR2(500);
top_row_qry VARCHAR2(500);
BEGIN
--To define multiple values for a collection e.g. ABC, XYZ
v_array.EXTEND(2) ;
v_array(1):='ABC' ;
v_array(2):='XYZ' ;
--identifers := t_array('ABC') ;
column_name := get_column_name(TYPE) ;
info_qry := 'select INS.i_id, INS.model from table1 INS where INS.'||column_name||'='''||VALUE||''' order by INS.version desc';
top_row_qry := 'select * from ('||info_qry||')' ;
OPEN out_param FOR top_row_qry ;
EXCEPTION
WHEN OTHERS THEN
OPEN out_param FOR 'select null, null from dual' ;
END get_something ;
/
--To execute the procedure
DECLARE
lv_type VARCHAR2(200);
lv_id NUMBER;
lv_cur SYS_REFCURSOR;
BEGIN
get_something('param1','param2',lv_cur);
LOOP
FETCH lv_cur INTO lv_id,lv_type;
EXIT WHEN lv_cur%NOTFOUND;
--Do something.....
END LOOP;
END;

Calling SP with sys_refcursor as out parameter inside another procedure

I have an SP
create or replace PROCEDURE ALTERNATE_NAME_LOOKUP
( P_NAME IN VARCHAR2,
P_TYPE IN VARCHAR2, retCursor OUT SYS_REFCURSOR
)
I didn't paste the rest of its body; The above procedure works fine on its own (with the body of course)
Now I want to call it from another stored procedure, and I want to traverse over the refcursor.
What I am doing is declaring an_last_cur SYS_REFCURSOR; and calling ALTERNATE_NAME_LOOKUP procedure as ALTERNATE_NAME_LOOKUP(p_req.LASTNAMEEXP,c_LAST, an_last_cur); It compiles.
but when I add following block -
ALTERNATE_NAME_LOOKUP('Roman Reigns','LAST',an_last_cur);
For alt in an_last_cur
Loop
DBMS_OUTPUT.PUT_LINE('ok');
end loop;
It gives compilation error -
PLS-00221: 'AN_LAST_CUR' is not a procedure or is undefined
What am I doing wrong?
create or replace procedure alternate_name_lookup
( p_name in varchar2, p_type in varchar2, retcursor out sys_refcursor )
as
begin
open retcursor for select * from user_objects ;
end;
set serveroutput on
declare
an_last_cur sys_refcursor;
type my_objects is table of user_objects%rowtype;
objects my_objects;
begin
alternate_name_lookup('Roman Reigns','LAST',an_last_cur);
fetch an_last_cur bulk collect into objects;
dbms_output.put_line(objects.count);
for indx in 1 .. objects.count
loop
dbms_output.put_line(objects(indx).object_name);
end loop;
close an_last_cur;
end;
Try this one. Hope this helps. I dont have workspace with me so pardon
syntax erro r if any.
CREATE OR REPLACE PROCEDURE test_ref_prc
( p_ref_out OUT sys_refcursor)
AS
BEGIN
OPEN p_ref_out FOR
SELECT LEVEL FROM DUAL CONNECT BY LEVEL < 10;
END;
CREATE OR REPLACE PROCEDURE test_ref2
AS
refc sys_refcursor;
num_ntt NUMBER_NTT;
BEGIN
test_ref_prc(refc);
FETCH refc BULK COLLECT INTO num_ntt;
FOR I IN num_ntt.FIRST..num_ntt.LAST LOOP
dbms_output.put_line(num_ntt(i));
END LOOP;
END;
exec test_ref2;

Resources