PL/SQL Procedure not returns any - oracle

I am trying to do a stored procedure in SQL Developer, which returns multiple records from a single table. But when I call the procedure, it returns the empty variables (taking into account that the table has records).
CREATE OR REPLACE PROCEDURE PURE_ENC_SELECCIONAR_INTERACCIONES(
startDate IN varchar2,
endDate IN varchar2,
o_interactionId OUT PURE_ENC_INTERACTION.INTERACTIONID%TYPE,
o_interactionDate OUT PURE_ENC_INTERACTION.INTERACTIONDATE%TYPE,
o_queueId OUT PURE_ENC_INTERACTION.QUEUEID%TYPE,
o_personId OUT PURE_ENC_INTERACTION.PERSONID%TYPE,
o_numSolicitud OUT PURE_ENC_INTERACTION.NUMSOLICITUD%TYPE,
o_customerDni OUT PURE_ENC_INTERACTION.CUSTOMERDNI%TYPE,
o_customerName OUT PURE_ENC_INTERACTION.CUSTOMERNAME%TYPE,
o_ani OUT PURE_ENC_INTERACTION.ANI%TYPE,
o_dnis OUT PURE_ENC_INTERACTION.DNIS%TYPE,
o_custom1 OUT PURE_ENC_INTERACTION.CUSTOM1%TYPE,
o_custom2 OUT PURE_ENC_INTERACTION.CUSTOM2%TYPE,
o_custom3 OUT PURE_ENC_INTERACTION.CUSTOM3%TYPE,
o_custom4 OUT PURE_ENC_INTERACTION.CUSTOM4%TYPE,
o_custom5 OUT PURE_ENC_INTERACTION.CUSTOM5%TYPE)
IS
BEGIN
FOR loop_int IN (
SELECT INTERACTIONID, INTERACTIONDATE, QUEUEID, PERSONID, NUMSOLICITUD, CUSTOMERDNI,
CUSTOMERNAME, ANI, DNIS, CUSTOM1, CUSTOM2, CUSTOM3, CUSTOM4, CUSTOM5
INTO o_interactionId, o_interactionDate, o_queueId, o_personId, o_numSolicitud,
o_customerDni, o_customerName, o_ani, o_dnis, o_custom1, o_custom2, o_custom3,
o_custom4, o_custom5
FROM PURE_ENC_INTERACTION )
--WHERE INTERACTIONDATE >= startDate AND INTERACTIONDATE < endDate )
LOOP
DBMS_OUTPUT.PUT_LINE('InteractionID: '|| o_interactionId);
END LOOP loop_int;
END;
I execute the procedure:
SET serveroutput ON
DECLARE
o_interactionId VARCHAR2(200);
o_interactionDate VARCHAR2(200);
o_queueId VARCHAR2(200);
o_personId VARCHAR2(200);
o_numSolicitud VARCHAR2(200);
o_customerDni VARCHAR2(200);
o_customerName VARCHAR2(200);
o_ani VARCHAR2(200);
o_dnis VARCHAR2(200);
o_custom1 VARCHAR2(200);
o_custom2 VARCHAR2(200);
o_custom3 VARCHAR2(200);
o_custom4 VARCHAR2(200);
o_custom5 VARCHAR2(200);
BEGIN
PURE_ENC_SELECCIONAR_INTERACCIONES(
'2019-10-20T12:30:03',
'2019-10-29T03:30:03',
o_interactionId,
o_interactionDate,
o_queueId,
o_personId,
o_numSolicitud,
o_customerDni,
o_customerName,
o_ani,
o_dnis,
o_custom1,
o_custom2,
o_custom3,
o_custom4,
o_custom5);
END;
When I run it, returns:
Procedimiento PL/SQL terminado correctamente.
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
InteractionID:
When I run this sample:
SELECT INTERACTIONID, INTERACTIONDATE, QUEUEID , PERSONID , NUMSOLICITUD , CUSTOMERDNI , CUSTOMERNAME , ANI , DNIS , CUSTOM1,CUSTOM2 ,CUSTOM3 ,CUSTOM4 ,CUSTOM5
FROM PURE_ENC_INTERACTION;
It returns all the registers fine.
What could be the problem?

Well, you didn't post what you exactly have. How do I know? Because the procedure has syntax errors. You can't use cursor FOR loop like that; INTO is required for SELECT statements in PL/SQL, but not where you used it.
Simplified, on Scott's schema, this is what you did:
SQL> create or replace procedure p_test (par_deptno in number, par_ename out varchar2) is
2 begin
3 for cur_r in (select ename from emp into par_ename
4 where deptno = par_deptno)
5 loop
6 dbms_output.put_line('Ename: ' || par_ename);
7 end loop;
8 end;
9 /
Warning: Procedure created with compilation errors.
SQL> show err
Errors for PROCEDURE P_TEST:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/17 PL/SQL: SQL Statement ignored
3/39 PL/SQL: ORA-00933: SQL command not properly ended
SQL>
As I said: your code is invalid.
This, on the other hand, is valid:
SQL> create or replace procedure p_test (par_deptno in number, par_ename out varchar2) is
2 begin
3 for cur_r in (select ename from emp
4 where deptno = par_deptno)
5 loop
6 par_ename := cur_r.ename;
7 dbms_output.put_line('Ename from P_TEST: ' || par_ename);
8 end loop;
9 end;
10 /
Procedure created.
SQL> declare
2 l_ename varchar2(20);
3 begin
4 p_test (10, l_ename);
5 dbms_output.put_line('Ename from anonymous PL/SQL block: ' || l_ename);
6 end;
7 /
Ename from P_TEST: CLARK
Ename from P_TEST: KING
Ename from P_TEST: MILLER
Ename from anonymous PL/SQL block: MILLER
PL/SQL procedure successfully completed.
SQL>
But, it is wrong (logically). The procedure fetched all employees (Clark, King, Miller), but the caller (i.e. the anonymous PL/SQL block) got only one value: the last one fetched by the cursor.
I doubt that this is what you want; doesn't make sense.
I don't know what you really want; perhaps it is to return all rows that satisfy certain condition. If that's the case, you can't return scalar values, that should be *something
else*. Ref cursor is one option, but - you don't need a procedure with bunch of parameters, then - maybe a function is a better option. For example:
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 from emp where deptno = par_deptno;
7 return l_rc;
8 end;
9 /
Function created.
SQL> select f_test(10) from dual;
F_TEST(10)
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ENAME
----------
CLARK
KING
MILLER
SQL>

Related

PL/SQL Procedure SELECT Input- Error PLS-00306

Hello I'm a beginner at PL/SQL and some help would be appreciated.
So I have this procedure here and my goal is to have it so that when this procedure is executed that I can enter a 5 digit integer (a zipcode) and it will just select those values from the table and display just as if I've done a query like
SELECT * FROM customers WHERE customer_zipcode = "input zipcode".
create or replace PROCEDURE LIST_CUSTOMER_ZIPCODE(
p_zipcode IN customers.customer_zipcode%TYPE,
p_disp OUT SYS_REFCURSOR)
-- User input Variable, Display Variable
IS
BEGIN
OPEN p_disp for SELECT customer_first_name, customer_zipcode FROM customers
WHERE customer_zipcode=p_zipcode;
EXCEPTION
-- Input Sanitization
WHEN no_data_found THEN
dbms_output.put_line('-1');
END;
EXEC LIST_CUSTOMER_ZIPCODE(07080);
When I execute this command I just keep getting this error.
https://i.stack.imgur.com/nCI8T.png
If you are using SQL*Plus or SQL Developer then you can declare a bind variable and then call the procedure passing the variable and then print it:
SELECT * FROM customers WHERE customer_zipcode = "input zipcode".
create or replace PROCEDURE LIST_CUSTOMER_ZIPCODE(
p_zipcode IN customers.customer_zipcode%TYPE,
p_disp OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN p_disp FOR
SELECT customer_first_name, customer_zipcode
FROM customers
WHERE customer_zipcode = p_zipcode;
EXCEPTION
-- Input Sanitization
WHEN no_data_found THEN
dbms_output.put_line('-1');
END;
/
VARIABLE cur SYS_REFCURSOR;
EXEC LIST_CUSTOMER_ZIPCODE('07080', :cur);
PRINT cur;
However, your exception handling block is never going to be called as the cursor can return zero rows without raising that exception so the procedure could be simplified to:
create or replace PROCEDURE LIST_CUSTOMER_ZIPCODE(
p_zipcode IN customers.customer_zipcode%TYPE,
p_disp OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN p_disp FOR
SELECT customer_first_name, customer_zipcode
FROM customers
WHERE customer_zipcode = p_zipcode;
END;
/
You can't just execute such a procedure as it expects 2 parameters; one is IN, while another is OUT (ref cursor which contains result set).
I don't have your tables so I'll demonstrate it using Scott's sample schema by passing department number and returning list of employees working in that department.
Procedure:
SQL> set serveroutput on
SQL> create or replace procedure p_list
2 (p_deptno in dept.deptno%type,
3 p_disp out sys_refcursor
4 )
5 is
6 begin
7 open p_disp for select ename, job from emp
8 where deptno = p_deptno;
9 end;
10 /
Procedure created.
This is how you use it:
SQL> declare
2 l_list sys_refcursor;
3 l_ename emp.ename%type;
4 l_job emp.job%type;
5 begin
6 p_list(10, l_list); --> calling the procedure; use 2 parameters
7
8 loop
9 fetch l_list into l_ename, l_job;
10 exit when l_list%notfound;
11 dbms_output.put_line(l_ename ||' - '|| l_job);
12 end loop;
13 end;
14 /
CLARK - MANAGER
KING - PRESIDENT
MILLER - CLERK
PL/SQL procedure successfully completed.
SQL>
TRY EXEC LIST_CUSTOMER_ZIPCODE(:p_Zipcode);
If you put ':' before any string, It will become substitution string and you can type your input.

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>

Assignment of one cursor to other cursor and looping through for loop

I have a cursor inside package specification like below
Create package pkgname
is
Cursor C1(report_date date) is select * from some_table where some_date=report_date;
procedure proc(repdate date)
end;
I want a functionality that assign this cursor C1 to other cursor in procedure of the same package body.
Create package body pkgname is
Procedure proc(repdate date)
Is
Cursor C2 is C1(repdate);
Begin
for j in C2 loop
--do some task;
end loop;
End;
End;
Why would you do that? If you declared the cursor in package specification, simply use it in package body. For example:
SQL> create or replace package pkg_test as
2 cursor c1 (par_job varchar2) is
3 select empno, ename from emp
4 where job = par_job;
5 procedure proc (par_job in varchar2);
6 end;
7 /
Package created.
SQL> create or replace package body pkg_test as
2 procedure proc (par_job in varchar2) is
3 begin
4 for cur_r in pkg_test.c1(par_job) loop --> here it is!
5 dbms_output.put_line(cur_r.empno ||' '|| cur_r.ename);
6 end loop;
7 end;
8 end;
9 /
Package body created.
SQL> set serveroutput on
SQL> exec pkg_test.proc('CLERK');
7369 SMITH
7876 ADAMS
7900 JAMES
PL/SQL procedure successfully completed.
SQL>

call pl/sql from another one in oracle database problem

i have 2 stored procedures 1 is called A with the following impl
PROCEDURE A(p_id IN NUMBER, lic_cat_2 OUT varchar2,lic_cat_1 OUT varchar2,traffic_code OUT varchar2,lic_type OUT varchar2,emp_num OUT varchar2)
// Some LOGIC
end A ;
and PROCEDURE B which is a wrapper to proc A but i need to get other value with a query
PROCEDURE B(ph_id IN NUMBER, lic_cat_2 OUT varchar2,lic_cat_1 OUT varchar2,traffic_code OUT varchar2,lic_type OUT varchar2,emp_num OUT varchar2)
declare number phone_id
begin
select into phone_id parent_id from per_phones where phone_id= p_id
exec A(phone_id,lic_cat_2 OUT varchar2,lic_cat_1 OUT varchar2,traffic_code OUT varchar2,lic_type OUT varchar2,emp_num OUT varchar2);
END B;
but it gives me PLS-00103: Encountered the symbol “CREATE”
You're calling the A procedure in a wrong manner:
omit EXEC, it is a SQL*Plus command
omit parameters' description (IN/OUT, datatype) - pass only values
omit DECLARE; you need it in triggers or anonymous PL/SQL blocks, but not in stored procedures
by the way, variable name comes first, datatype next (for phone_id)
I'd suggest you to prefix parameters and variables with p_ (or par_) and l_ respectively (or any other prefix you want) to distinguish them from column names. Otherwise, it is easy to get confused.
also, use table aliases in your queries for the same reason
So:
CREATE OR REPLACE PROCEDURE B (p_ph_id IN NUMBER,
p_lic_cat_2 OUT VARCHAR2,
p_lic_cat_1 OUT VARCHAR2,
p_traffic_code OUT VARCHAR2,
p_lic_type OUT VARCHAR2,
p_emp_num OUT VARCHAR2)
IS
l_phone_id NUMBER;
BEGIN
SELECT p.parent_id
INTO l_phone_id
FROM per_phones p
WHERE p.phone_id = p_ph_id;
A (l_phone_id,
p_lic_cat_2,
p_lic_cat_1,
p_traffic_code,
p_lic_type,
p_emp_num);
END B;
As I don't have your tables, for example (to show how to do it) I used Scott's sample schema:
SQL> create or replace procedure a (par_deptno in number, par_dname out varchar2)
2 is
3 begin
4 select dname into par_dname from dept where deptno = par_deptno;
5 end;
6 /
Procedure created.
SQL>
SQL> create or replace procedure b (par_empno in number, par_dname out varchar2) is
2 l_deptno emp.deptno%type;
3 begin
4 select deptno into l_deptno from emp where empno = par_empno;
5
6 a(l_deptno, par_dname);
7 end;
8 /
Procedure created.
SQL>
SQL> set serveroutput on
SQL> declare
2 l_dname dept.dname%type;
3 begin
4 b (7654, l_dname);
5 dbms_output.put_line('Dname = ' || l_dname);
6 end;
7 /
Dname = SALES
PL/SQL procedure successfully completed.
SQL>

What does :1 mean in dynamic sql

vsql='select ename into y from emp where empno=:1'
what does :1 mean here?
It is a placeholder for a parameter value you'll be using.
For example:
SQL> set serveroutput on
SQL> declare
2 l_empno number := 7902;
3 v_sql varchar2(200);
4 l_ename varchar2(20);
5 begin
6 v_sql := 'select ename from emp where empno = :1';
7 execute immediate v_sql into l_ename using l_empno; --> this
8 dbms_output.put_line(l_ename);
9 end;
10 /
FORD
PL/SQL procedure successfully completed.
SQL>

Resources