How to use outputs from a function? - oracle

I have a function with three outputs and one input. But how do I use the value that comes from the outputs? I need to check the values ​​coming out of the outputs. Can someone explain to me how I do it?

As Koen has already said, you don't want to use a function in this case - use a procedure instead. Here's an example: procedure accepts empno and returns their name and salary via OUT parameters.
SQL> create or replace procedure p_test (par_empno in number, par_ename out varchar2, par_sal out number)
2 is
3 begin
4 select ename, sal
5 into par_ename, par_sal
6 from emp
7 where empno = par_empno;
8 end;
9 /
Procedure created.
This is one employee; use its empno when calling the procedure:
SQL> select empno, ename, sal from emp where rownum = 1;
EMPNO ENAME SAL
---------- ---------- ----------
7369 SMITH 920
SQL> set serveroutput on
To call the procedure, declare local variables (because you have to put the result into something):
SQL> declare
2 l_ename emp.ename%type;
3 l_sal emp.sal%type;
4 begin
5 p_test(7369, l_ename, l_sal);
6 dbms_output.put_line(l_ename ||' earns ' || l_sal);
7 end;
8 /
SMITH earns 920
PL/SQL procedure successfully completed.
SQL>
If it must be a function, code changes slightly as function has to return a value anyway (not just via OUT parameters); I chose to return deptno value:
SQL> create or replace function f_test (par_empno in number, par_ename out varchar2, par_sal out number)
2 return varchar2
3 is
4 l_deptno emp.deptno%type;
5 begin
6 select ename, sal, deptno
7 into par_ename, par_sal, l_deptno
8 from emp
9 where empno = par_empno;
10
11 return l_deptno;
12 end;
13 /
Function created.
SQL> declare
2 l_ename emp.ename%type;
3 l_sal emp.sal%type;
4 l_deptno emp.deptno%type;
5 begin
6 l_deptno := f_test(7369, l_ename, l_sal);
7 dbms_output.put_line(l_ename ||' earns ' || l_sal || ' and works in department ' || l_deptno);
8 end;
9 /
SMITH earns 920 and works in department 20
PL/SQL procedure successfully completed.
SQL>

Related

print refcursor from function

I'm using oracle 11 XE & Application Express 4.0.2.00.09 and I have this function that I want to print it's cursor. I don't know how to read the return of this function when it's called.
CREATE OR REPLACE FUNCTION stuff
RETURN sys_refcursor IS
rf_cur sys_refcursor;
BEGIN
OPEN rf_cur FOR
SELECT ename
FROM emp
WHERE sal = (SELECT MAX(sal)
FROM emp);
RETURN rf_cur;
END;
A simple option is to just select it (as any other function), but I guess that's not what you want:
SQL> select stuff from dual;
STUFF
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ENAME
----------
KING
Another option requires PL/SQL (I guess that is what you're looking for):
SQL> set serveroutput on
SQL> declare
2 l_rc sys_refcursor;
3 l_ename emp.ename%type;
4 begin
5 l_rc := stuff;
6 fetch l_rc into l_ename;
7 dbms_output.put_line(l_ename);
8 end;
9 /
KING
PL/SQL procedure successfully completed.
SQL>

don;t know why code is not working oracle live sql ,getting errors like ORA-06512: at "SYS.DBMS_SQL", line 1721

DECLARE
v_annual_salary NUMBER;
BEGIN
SELECT SAL * 12 INTO v_annual_salary
FROM EMP,DEPT
WHERE EMPNO = 7722;
DBMS_OUTPUT.PUT_LINE ('Annual Salary of 7722 is ' || TO_CHAR(v_annual_salary));
END;
/
Unless DEPT table contains a single row, this query will return TOO_MANY_ROWS. Why do you cross-join EMP and DEPT? Should have been just
SQL> declare
2 v_annual_salary number;
3 begin
4 select sal * 12
5 into v_annual_salary
6 from emp
7 where empno = 7934;
8
9 dbms_output.put_line('Annual salary of 7934 is ' || to_char(v_annual_salary));
10 end;
11 /
Annual salary of 7934 is 15600
PL/SQL procedure successfully completed.
SQL>
(My EMP table doesn't have employee whose EMPNO = 7722 so I used 7934).

How to call and save the result set of oracle stored procedure which returns ref cursor in a procedure

I am trying to call a existing procedure in my new procedure:
Retrievedata returns a OUT sys_refcursor
I am trying to save the output result of Retrievedata procedure.
TYPE Doc IS REF CURSOR;
Doc := PKG_search.Retrievedata(IN_Id);
I am getting the following error:
PLS-00321: expression 'DOC' is inappropriate as the left hand side of an assignment statement
Thanks in Advance!
It wouldn't hurt if you posted some more info. My lucky guess is:
Function that returns refcursor (if you do have a procedure, it has to have an OUT parameter, but - that's not what code you posted suggests):
SQL> create or replace function f_test (par_deptno in number)
2 return sys_refcursor
3 is
4 l_rc sys_refcursor;
5 begin
6 open l_rc for select ename, job
7 from emp
8 where deptno = par_deptno;
9 return l_rc;
10 end;
11 /
Function created.
Procedure which uses that function, gets refcursor and displays it contents:
SQL> create or replace procedure p_test (par_deptno in number)
2 is
3 l_rc sys_refcursor;
4 --
5 l_ename emp.ename%type;
6 l_job emp.job%type;
7 begin
8 l_rc := f_test(par_deptno);
9
10 loop
11 fetch l_rc into l_ename, l_job;
12 exit when l_rc%notfound;
13 dbms_output.put_line(l_ename ||' - '|| l_job);
14 end loop;
15 close l_rc;
16 end;
17 /
Procedure created.
Testing:
SQL> set serveroutput on
SQL> exec p_test(10);
CLARK - MANAGER
KING - PRESIDENT
MILLER - CLERK
PL/SQL procedure successfully completed.
SQL>
If it is a procedure with an OUT parameter, then:
SQL> create or replace procedure p_one (par_deptno in number, par_out out sys_refcursor)
2 is
3 begin
4 open par_out for select ename, job
5 from emp
6 where deptno = par_deptno;
7 end;
8 /
Procedure created.
SQL> create or replace procedure p_test (par_deptno in number)
2 is
3 l_rc sys_refcursor;
4 --
5 l_ename emp.ename%type;
6 l_job emp.job%type;
7 begin
8 p_one (par_deptno, l_rc);
9
10 loop
11 fetch l_rc into l_ename, l_job;
12 exit when l_rc%notfound;
13 dbms_output.put_line(l_ename ||' - '|| l_job);
14 end loop;
15 close l_rc;
16 end;
17 /
Procedure created.
SQL> set serveroutput on
SQL> exec p_test(10);
CLARK - MANAGER
KING - PRESIDENT
MILLER - CLERK
PL/SQL procedure successfully completed.
SQL>

Oracle stored procedure error on select

I am getting
ORA-06550: line 2, column 1:
PLS-00306: wrong number or types of arguments in call to 'GET_EMP_RS'
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
Error while executing select command stored procedure in oracle. My Procedure is
CREATE OR REPLACE
PROCEDURE get_emp_rs (p_deptno IN emp.EMPNO%TYPE,
p_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN p_recordset FOR
SELECT ENAME,
JOB,
MGR
FROM emp
WHERE EMPNO = p_deptno
ORDER BY ENAME;
END;
/
You are not calling the procedure properly.
In SQL*Plus, you could do it as:
SQL> CREATE OR REPLACE
2 PROCEDURE get_emp_rs(
3 p_deptno IN emp.DEPTNO%TYPE,
4 p_recordset OUT SYS_REFCURSOR)
5 AS
6 BEGIN
7 OPEN p_recordset FOR
8 SELECT ENAME, JOB, MGR
9 FROM emp
10 WHERE DEPTNO = p_deptno
11 ORDER BY ENAME;
12 END;
13 /
Procedure created.
SQL>
SQL> SHOW ERRORS
No errors.
SQL>
SQL> variable cur refcursor
SQL>
SQL> DECLARE
2 cur SYS_REFCURSOR;
3 BEGIN
4 get_emp_rs(10, :cur);
5 END;
6 /
PL/SQL procedure successfully completed.
SQL>
SQL> print cur;
ENAME JOB MGR
---------- --------- ----------
CLARK MANAGER 7839
KING PRESIDENT
MILLER CLERK 7782
SQL>
Or,
It can be referenced from PL/SQL as:
SQL> DECLARE
2 l_cursor SYS_REFCURSOR;
3 l_ename emp.ename%TYPE;
4 l_job emp.job%TYPE;
5 l_mgr emp.mgr%TYPE;
6 BEGIN
7 get_emp_rs (p_deptno => 10, p_recordset => l_cursor);
8 LOOP
9 FETCH l_cursor INTO l_ename, l_job, l_mgr;
10 EXIT
11 WHEN l_cursor%NOTFOUND;
12 DBMS_OUTPUT.PUT_LINE(l_ename || ' | ' || l_job || ' | ' || l_mgr);
13 END LOOP;
14 CLOSE l_cursor;
15 END;
16 /
CLARK | MANAGER | 7839
KING | PRESIDENT |
MILLER | CLERK | 7782
PL/SQL procedure successfully completed.
SQL>

How do I pass a list of numbers into a stored procedure?

So I have the following stored procedure:
CREATE OR REPLACE PROCEDURE stored_p
(
ntype IN NUMBER ,
p_ResultSet OUT TYPES.cursorType
)
AS
BEGIN
OPEN p_ResultSet FOR
select * from table where ttype in ntype;
END stored_p
and, I can call it like this:
VARIABLE resultSet REFCURSOR
EXEC stored_p(80001, :resultSet);
PRINT :resultSet
but I want to be able to call it like this:
VARIABLE resultSet REFCURSOR
EXEC stored_p([80001,80002], :resultSet);
PRINT :resultSet
How should I modify my stored procedure accordingly? I am doing this so that I can display the results in a Crystal Report... (just in case that affects anything).. Thanks!!
The best option would be to pass a collection
SQL> create type empno_tbl
2 is
3 table of number;
4 /
Type created.
SQL> create or replace procedure stored_p
2 (
3 empnos in empno_tbl,
4 p_rc out sys_refcursor )
5 as
6 begin
7 open
8 p_rc for select * from emp where empno in (select * from table(empnos));
9 end;
10 /
Procedure created.
SQL> var rc refcursor;
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure stored_p
2 (
3 empnos in empno_tbl,
4 p_rc out sys_refcursor )
5 as
6 begin
7 open
8 p_rc for select * from emp where empno in (select * from table(empnos));
9* end;
SQL> begin
2 stored_p( new empno_tbl(7902,7934), :rc );
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> print rc
EMPNO ENAME JOB MGR HIREDATE SAL COMM
---------- ---------- --------- ---------- --------- ---------- ----------
DEPTNO FAKE_COL FOO
---------- ---------- ----------
7902 FORD ANALYST 7566 03-DEC-81 3000
20 1
7934 MILLER CLERK 7782 23-JAN-82 1300
10 1
Unfortunately, Crystal Reports may not be able to pass a proper collection to a stored procedure. If that is the case, you'd have to pass in a comma-separated list of numbers. Your procedure would then have to parse that comma-separated string into a collection. You can use (or modify) Tom Kyte's in_list function for this
SQL> ed
Wrote file afiedt.buf
1 create or replace function in_list(
2 p_string in varchar2
3 )
4 return empno_tbl
5 as
6 l_string long default p_string || ',';
7 l_data empno_tbl := empno_tbl();
8 n number;
9 begin
10 loop
11 exit when l_string is null;
12 n := instr( l_string, ',' );
13 l_data.extend;
14 l_data(l_data.count) :=
15 ltrim( rtrim( substr( l_string, 1, n-1 ) ) );
16 l_string := substr( l_string, n+1 );
17 end loop;
18 return l_data;
19* end;
SQL> /
Function created.
SQL> ed
Wrote file afiedt.buf
1 create or replace procedure stored_p
2 (
3 empnos in varchar2,
4 p_rc out sys_refcursor )
5 as
6 begin
7 open p_rc
8 for select *
9 from emp
10 where empno in (select *
11 from table(in_list(empnos)));
12* end;
SQL> /
Procedure created.
SQL> ed
Wrote file afiedt.buf
1 begin
2 stored_p( '7902,7934', :rc );
3* end;
SQL> /
PL/SQL procedure successfully completed.
SQL> print rc
EMPNO ENAME JOB MGR HIREDATE SAL COMM
---------- ---------- --------- ---------- --------- ---------- ----------
DEPTNO FAKE_COL FOO
---------- ---------- ----------
7902 FORD ANALYST 7566 03-DEC-81 3000
20 1
7934 MILLER CLERK 7782 23-JAN-82 1300
10 1
Newer versions might have different options. I work some with Oracle 9 and 10, and I will typically pass in a string of comma-separated values and dynamically build the SQL. There are some significant dangers with SQL injection to be aware of, though.
You need to create a type..
create or replace type NUMBER_ARRAY as table of number;
CREATE OR REPLACE PROCEDURE stored_p
(
ntype IN NUMBER_ARRAY ,
p_ResultSet OUT TYPES.cursorType
)
You can loop it using..
for i in 1 .. ntype.count
loop
dbms_output.put_line( ntype(i) );
end loop;
To test it,
DECLARE
ntypetest NUMBER_ARRAY := NUMBER_ARRAY ();
BEGIN
FOR i IN 1 .. 5
LOOP
ntypetest.EXTEND;
ntypetest (i) := i;
END LOOP;
stored_p(ntypetest,..)
There may be some variation in syntax.
Of course you can pass in comma separated values too but that will come in as a string. Your string should be something like 'val1','val2','val3'. You need to be careful when you have numbers as the whole string will look like in ('2343,3444,2222') which will be treated as one value instead of multiple numbers as in (2343,3444,2222)

Resources