Is it possible to use "return" in stored procedure? - oracle

CREATE PROCEDURE Pname(in_Tid IN VARCHAR2,in_IP IN VARCHAR2,outstaticip OUT VARCHAR2,outcount OUT NUMBER)
AS
BEGIN
select STATIC_IP into outstaticip from OP_TTER_MAPPING where TERMINAL_ID = in_Tid;
if in_IP = outstaticip then
return 1;
else
select COUNT(*) into outcount from OP_TTER_MAPPING where DYNAMIC_IP_LOW <= in_IP AND DYNAMIC_IP_HIGH >= in_IP AND TERMINAL_ID = in_Tid;
if outcount = 1 then
return 1;
else
return 0;
end if;
end if;
END;
Is it possible to use return in stored procedure like above?
If we can use return, how can i get that return value in Executesql("begin Pname(----)END") method
EDIT
Now I edited my return value in stored procedure like this, am I doing it right ?
CREATE PROCEDURE P_ValidateTIDIP(in_Tid IN VARCHAR2,in_IP IN VARCHAR2,outstaticip OUT VARCHAR2,outcount OUT NUMBER,outretvalue OUT NUMBER)
AS
BEGIN
select STATIC_IP into outstaticip from OP_TTER_MAPPING where TERMINAL_ID = in_Tid;
if in_IP = outstaticip then
outretvalue:=1;
else
select COUNT(*) into outcount from OP_TTER_MAPPING where DYNAMIC_IP_LOW <= in_IP AND DYNAMIC_IP_HIGH >= in_IP AND TERMINAL_ID = in_Tid;
if outcount = 1 then
outretvalue:=1;
else
outretvalue:=0;
end if;
end if;
END;

In Stored procedure, you return the values using OUT parameter ONLY. As you have defined two variables in your example:
outstaticip OUT VARCHAR2, outcount OUT NUMBER
Just assign the return values to the out parameters i.e. outstaticip and outcount and access them back from calling location. What I mean here is: when you call the stored procedure, you will be passing those two variables as well. After the stored procedure call, the variables will be populated with return values.
If you want to have RETURN value as return from the PL/SQL call, then use FUNCTION. Please note that in case, you would be able to return only one variable as return variable.

Use FUNCTION:
CREATE OR REPLACE FUNCTION test_function
RETURN VARCHAR2 IS
BEGIN
RETURN 'This is being returned from a function';
END test_function;

-- IN arguments : you get them. You can modify them locally but caller won't see it
-- IN OUT arguments: initialized by caller, already have a value, you can modify them and the caller will see it
-- OUT arguments: they're reinitialized by the procedure, the caller will see the final value.
CREATE PROCEDURE f (p IN NUMBER, x IN OUT NUMBER, y OUT NUMBER)
IS
BEGIN
x:=x * p;
y:=4 * p;
END;
/
SET SERVEROUTPUT ON
declare
foo number := 30;
bar number := 0;
begin
f(5,foo,bar);
dbms_output.put_line(foo || ' ' || bar);
end;
/
-- Procedure output can be collected from variables x and y (ans1:= x and ans2:=y) will be: 150 and 20 respectively.
-- Answer borrowed from: https://stackoverflow.com/a/9484228/1661078

It is possible.
When you use Return inside a procedure, the control is transferred to the calling program which calls the procedure. It is like an exit in loops.
It won't return any value.

CREATE PROCEDURE pr_emp(dept_id IN NUMBER,vv_ename out varchar2 )
AS
v_ename emp%rowtype;
CURSOR c_emp IS
SELECT ename
FROM emp where deptno=dept_id;
BEGIN
OPEN c;
loop
FETCH c_emp INTO v_ename;
return v_ename;
vv_ename := v_ename
exit when c_emp%notfound;
end loop;
CLOSE c_emp;
END pr_emp;

Related

PL/SQL "all_search" procedure is not a procedure or is undefined

This function is inside a package, but when I call the function the following error appears: PL/SQL "all_search" is not a procedure or is undefined. Someone can help me?
CREATE OR REPLACE PACKAGE employee_tab IS
FUNCTION all_search (ID_EMP in NUMBER) RETURN O_T_EMPL PIPELINED;
END employee_tab;
/
CREATE OR REPLACE TYPE O_T_EMPL AS TABLE OF O_EMPLOYEE;
/
CREATE OR REPLACE PACKAGE BODY employee_tab IS
FUNCTION all_search (ID_EMP in NUMBER) RETURN O_T_EMPL PIPELINED
IS
TAB_OBJC_EMP O_T_EMPL;
MY_QUERY_SEARCH VARCHAR2(400);
REF_C SYS_REFCURSOR;
MAX_ROW NUMBER := 25;
BEGIN
MY_QUERY_SEARCH := 'SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID = ID_EMP';
open REF_C for MY_QUERY_SEARCH using ID_EMP;
loop
--
fetch REF_C bulk collect into TAB_OBJC_EMP limit MAX_ROW;
exit when TAB_OBJC_EMP.count = 0;
for i in 1..TAB_OBJC_SEE.count
--
loop
pipe row(O_EMPLOYEE(TAB_OBJC_EMP(i).V_O_EMP_ID,
TAB_OBJC_EMP(i).V_O_HIRE_ID,
TAB_OBJC_EMP(i).V_O_DEP_ID)
);
end loop;
--
END loop;
--
CLOSE REF_C;
RETURN;
--
END all_search;
END employee_tab;
/
call function: employee_tab.all_search(1);
You need to assign the result of the function to something, try something like:
DECLARE
l_emp_id NUMBER;
BEGIN
SELECT EMP_ID
INTO l_emp_id
FROM TABLE(employee_tab.all_search(1))
WHERE rownum = 1;
DBMS_OUTPUT.put_line(TO_CHAR(EMP_ID));
END;
/

How to count rows from two columns?

I try to create the function login that takes customer number(pnr) and password from same table. Its fine to create function but test crashes with following eror:
ORA-00904: "P_PASSWD": invalid identifier
create or replace function logga_in(
p_pnr bankkund.pnr%type,
p_passwd bankkund.passwd%type
)
return number
as
v_resultat number(1);
begin
select count(pnr) into v_resultat
from bankkund
where p_pnr = pnr
and p_passwd = passwd;
return 1;
exception
when no_data_found then
return 0;
end;
There is one other problem with your code not suggested in the comments, A count function from a select into will not raise a NO_DATA_FOUND exception. You may use an IF condition on count or do something like this, which is preferable
CREATE OR REPLACE FUNCTION logga_in (
p_pnr bankkund.pnr%TYPE,
p_passwd bankkund.passwd%TYPE
) RETURN NUMBER AS
v_resultat NUMBER(1);
BEGIN
SELECT 1 --do not use count if you wish to handle no_data_found
INTO v_resultat FROM
bankkund WHERE pnr = p_pnr AND
passwd = p_passwd
AND ROWNUM = 1; --Add this
RETURN 1;
EXCEPTION
WHEN no_data_found THEN
RETURN 0;
END;
Now, as far as calling the procedure is concerned, there are various options available including using bind variable
VARIABLE p_pnr number --use the datatype of bankkund.pnr%TYPE
VARIABLE p_passwd VARCHAR2(10) --use the datatype of bankkund.passwd
SELECT logga_in(:p_pnr,:p_passwd) FROM dual;
Or substitution variable
SELECT logga_in('&p_pnr','&p_passwd') FROM dual;
Give inputs when prompted.
Or use PL/SQL block
DECLARE
v_res INT;
v_pnr bankkund.pnr%type := 12892; --or appropriate value
p_passwd bankkund.passwd%type := some_passwd';
BEGIN
v_res := logga_in();
If v_res = 1 THEN
do_something_u_want; --call or execute appropriate action.
END IF;
END;
/

dbms_output in function from package does not showed

I need to know what employee_ids has been updated in a function from a package for the HR Oracle Schema. For this I tried to execute a dbms_output function inside another function in this package but the output only shows the return value fron the function, not the output.
What is the right form to get this?, here is the code from the package and its function:
create or replace package body pac_busqueda_empleados7 as
function f_cambia_datos_empl( p_nom in employees.first_name%TYPE)
return number is
i NUMBER := 0;
v_val_nom employees.first_name%type;
ids dbms_sql.number_table;
begin
v_val_nom := p_nom;
update employees set first_name = 'NN' where employees.first_name=v_val_nom return employees.employee_id bulk collect into ids;
return 1;
for i in ids.first .. ids.last loop
dbms_output.put_line('Updated: ' || ids(i));
end loop;
exception when others then
return 0;
end;
end pac_busqueda_empleados7;
And this is the execution block from this package function.
declare
v_nombre employees.first_name%type;
v_resultado number;
begin
v_nombre := 'Nombre';
v_resultado:=pac_busqueda_empleados7.f_cambia_datos_empl(v_nombre);
dbms_output.put_line(v_resultado);
end;
the output expected should be:
1
Updated: 100
Updated: 101
Updated: 102
Updated: 103
.
.
.
etc.
But for now is only:
1
PL/SQL procedure successfully completed.
Look carefully at this part of your code:
begin
v_val_nom := p_nom;
update employees set first_name = 'NN' where employees.first_name=v_val_nom return employees.employee_id bulk collect into ids;
return 1;
for i in ids.first .. ids.last loop
dbms_output.put_line('Updated: ' || ids(i));
end loop;
You return from the function before the loop starts.
Place return statement after the loop and you should get the desired output.

Comparing number with varchar2

I have this function and I need to compare number with varchar.
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return number as
begin
declare odd integer;
declare i_perecentage=0;
begin
if i_odd ='SP'
then
return (0);
end if;
odd:=round(to_number((1-i_perecentage/100)*i_odd),2);
if odd<1
then
return(i_odd);
else
return(round(odd,2));
end if;
end;
end;
/
PS: I edited function and i resolve problem with comparing , now i have another situation that i dont like..
This function returns calculated percentage of i_odd. The problem is that if i pass 0 in i_percentage in results i get result with no decimal places(for example: i_odd = 3.10 and i_percentage = 0 i get odd = 3 but if I pass i_odd = 3.10 and i_percentage = 1 i get odd = 3.10 ).
Why is on i_percentage = 0 i dont get decimal places ??
If you want to validate a varchar2 field as a number in PL/SQL, typically you'd just try converting it to a number and catch the exception.
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return number as
odd number;
BEGIN
-- if i_odd = 'SP' (or another non-number), this will throw an ORA-01722
-- exception which will be caught in the exception block, below
odd := to_number(i_odd); -- you might want a format mask here
--... now you can use "odd" as a number
EXCEPTION WHEN INVALID_NUMBER THEN
return 0;
END;
/
You can also nest a begin..end block in the middle of your code just to catch exceptions, if that works better for you:
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return number as
odd number;
begin
begin
odd := to_number(i_odd); -- you might want a format mask here
exception when INVALID_NUMBER then
odd := 0;
end;
--... now you can use "odd" as a number
end;
/
The reason why you can't catch the invalid_number exception is because you are declaring the input parameter as a number. When you call your function, Oracle tries to convert the string to a number first (and it fails of course, before entering your code at all).
If you change the input parameter to varchar2, then the conversions to number (implicit in this case) is done inside the function, and invalid numbers can be caught and handled as you want (here I'm just returning a different string to denote the issue):
create or replace function is_odd_even(i_num in varchar2)
return varchar2
is
begin
-- conversion to number is done here
if (mod(i_num, 2) = 0) then
return 'EVEN';
else
return 'ODD';
end if;
exception
when INVALID_NUMBER or VALUE_ERROR then
-- do something meaningful
return 'INV';
end;
Usage example:
with x as (
select '1' as val from dual
union all
select 'SP' as val from dual
union all
select '2' as val from dual
)
select x.val, is_odd_even(x.val)
from x;
Output:
1 ODD
SP INV
2 EVEN
SOLUTION:
CREATE OR REPLACE FUNCTION getOdds(i_odd in varchar2, i_id in number) return varchar2 as
odd varchar2(10);
ret_value number(4);
begin
if (i_odd ='SP') or i_odd is null then
return 'SP';
else
odd :=ROUND( TO_NUMBER( ( 1 - (play_beting.get_odds_percentage(i_id) / 100 ) ) * TO_NUMBER(i_odd) ), 2);
IF(odd < 1) THEN
ret_value := TO_NUMBER(i_odd);
ELSE
ret_value := to_char(odd,'9999.00');
END IF;
END IF;
RETURN to_char(ret_value,'9999.00');
END getOdds;

Where in stored procedure I can make exit status?

I have oracle stored procedure where i check sender I'd,source system, and transaction number at the beginning of the procedure. Can I do it this way:
If Id != "aaa"
Exit -1;
Else if source = " ".
Exit -1;
Else if trans = " ".
Exit -1;
Else.
-- continues stored procedure
I appreciate any help
To rephrase your question more generally, you want a caller of your routine to know if something bad has happened inside it. There are (at least) three ways of doing this in PL/SQL.
Use an OUT parameter
Procedure cannot return a value, the way a function does, but it can set an output parameter:
CREATE PROCEDURE inner (p_id IN VARCHAR2(10), p_res OUT NUMBER)
IS
BEGIN
p_res := 0; -- default value
IF p_id = 'aaa' THEN
p_res := -1;
RETURN;
ELSE
-- do something
END IF;
END;
Then in the caller you would have:
DECLARE res NUMBER;
...
inner('aaa', res);
IF res = -1 THEN
-- panic!
END IF;
...
Use a function
Despite your seeming aversion to functions, this might be an option.
CREATE FUNCTION inner (p_id IN VARCHAR2(10))
RETURN NUMBER
IS
BEGIN
IF p_id = 'aaa' THEN
RETURN -1;
END IF;
-- do something
RETURN 0;
END;
Then in the caller:
...
IF inner('aaa') = -1 THEN
-- panic!
END IF;
...
Use an exception
Similar to other programming languages, PL/SQL has exceptions:
CREATE PROCEDURE inner (p_id IN VARCHAR2(10))
IS
BEGIN
IF p_id = 'aaa' THEN
RAISE_APPLICATION_ERROR(-20000, 'ID cannot be ''aaa''');
ELSE
-- do something
END IF;
END;
and in the caller:
...
DECLARE
panic EXCEPTION; -- declare exception
PRAGMA EXCEPTION_INIT (panic, -20000); -- assign error code to exception
...
BEGIN
inner ('aaa');
EXCEPTION
WHEN panic THEN
-- proceed to panic
END;
You are using a wrong syntax both for the IF...ELSE and for the exit.
Given that you are saying you need to get a return value, you probably need a function like this, using CASE:
create or replace function testFun ( pIn1 varchar2, pIn2 varchar2) return varchar2 is
begin
case
when pIn1 is null then
return -1;
when pIn2 = ' ' then
return -2;
else
return 999;
end case;
end;

Resources