I want to see values of object as output.
My PL/SQL Code:
CREATE OR REPLACE PROCEDURE XPROC( p_val IN xxx%TYPE DEFAULT NULL,
p_debt_receivable_out OUT SYS_REFCURSOR)
IS
invoice_det get_debt_type;
BEGIN
insert into tmp_invoice_det xxxxxxxxx;
select get_debt_obj(INVOICE_NUMBER,
INVOICE_DATE,
INVOICE_PERIOD,
DUE_AMOUNT,
DUE_DATE,
INVOICE_STATUS,
INVOICE_ADDRESS) bulk collect into
invoice_det from tmp_invoice_det;
OPEN p_debt_receivable_out FOR
select total_debt,TOTAL_RECEIVABLE,invoice_det as invoice_detail from xxxxxxxxx;
END;
How I call:
set serveroutput on
variable result refcursor
DECLARE
p_val VARCHAR2(144);
BEGIN
p_val:= ‘12345’;
XPROC(p_val, :result);
END;
/
print result;
OUTPUT:
TOTAL_DEBT
TOTAL_RECEIVABLE
INVOICE_DETAIL
159
0
GET_DEBT_TYPE([CDR_INQUIRY.GET_DEBT_OBJ],[CDR_INQUIRY.GET_DEBT_OBJ],[CDR_INQUIRY.GET_DEBT_OBJ])
EXPECTED OUTPUT:
TOTAL_DEBT
TOTAL_RECEIVABLE
INVOICE_DETAIL
159
0
INVOICE_DETAIL: value , INVOICE_DATE: value ,INVOICE_PERIOD: value, ......
Related
I am new to plsql i try to run the piece of code but it is giving error and not able to debug
create or replace type final as object ( ename1 varchar2(10), sal1
NUMBER(7,2));--object
create or replace type construct is table of final; /*nested table of
object type */
create or replace function returnmore (empno1 number) /*Function to
return more*/
return construct
AS
vemp construct:=construct();
vename varchar2(10);
vsal1 NUMBER(7,2);
begin
select ENAME,sal into vename,vsal1 from emp where empno=empno1;
vemp.extend;
vemp(1):=construct(vename,vsal1);
return vemp;
end;
But gives me an error
Function SYSTEM.RETURNMORE#loacaDB
Error(11,1): PL/SQL: Statement ignored
Error(11,10): PLS-00306: wrong number or types of arguments in call to 'CONSTRUCT'
I am using oracle10gxe and sqldeveloper4.2
You can prefer using non-preserved keyword such as typ_emp instead of final which's reserved.
SQL> create or replace type typ_emp as object ( ename1 varchar2(10), sal1 number(7,2));
SQL> create or replace type construct is table of typ_emp;
and you can convert your function as below :
create or replace function returnmore( empno1 emp.empno%type )
return construct AS
vemp construct := construct();
vename varchar2(10);
vsal1 number(7, 2);
begin
select ename, sal into vename, vsal1 from emp where empno = empno1;
vemp.extend;
vemp(1) := typ_emp(vename, vsal1);
dbms_output.put_line(vemp(1).ename1);
return vemp;
end;
/
or another way to handle the same operation :
SQL> create or replace function returnmore( empno1 emp.empno%type )
return construct AS
vemp construct := construct();
v_sql varchar2(2000);
begin
v_sql := 'select typ_emp(ename, sal) from emp where empno = :v_empno1';
execute immediate v_sql bulk collect into vemp using empno1;
dbms_output.put_line(vemp(1).ename1);
return vemp;
end;
/
and test by invoking
SQL> set serveroutput on;
SQL> declare
result construct;
begin
result := returnmore( 1 ); -- 1 is just an ordinary presumed value for empno
end;
/ --> this will return the employee name as printed.
P.S. Never ever use SYSTEM user for non-administrative purposes. May be extremely harmful for your database.
I have created a simple procedure to reverse a number in PL/SQL. The procedure executes fine, but the result doesn't get print. Here's the proc,
CREATE OR REPLACE PROCEDURE SAMPLE_REV (myinput IN NUMBER, finalresult OUT NUMBER)
IS
OperInput NUMBER;
MYREMAINDER NUMBER;
MYRESULT NUMBER;
BEGIN
OperInput:=myinput;
while OperInput!=0 LOOP
MYREMAINDER:=mod(OperInput,10);
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
OperInput:=TRUNC(OperInput/10);
end LOOP;
finalresult:=MYRESULT;
END;
Procedure, when executed works fine. But, when I call on the procedure by the following code,
DECLARE
ENTER NUMBER;
finalresult NUMBER;
BEGIN
ENTER:=&ENTER;
SAMPLE_REV(ENTER,finalresult);
dbms_output.put_line('Output is '|| finalresult);
END;
The result is empty as,
Output is
PL/SQL procedure successfully completed.
I can't come to know the error here, if any. And thanks for the help.
the procedure is using MYRESULT before it is initialized hence null. So this line:
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
is essentially
MYRESULT:=(<<<NULL>>>*10)+MYREMAINDER;
So null overall.
Just adding a :=0 to the declaration will get it working. Also add the set serveroutput on
SQL>set serveroutput on
SQL>CREATE OR REPLACE PROCEDURE SAMPLE_REV (myinput IN NUMBER, finalresult OUT NUMBER)
2 IS
3 OperInput NUMBER;
4 MYREMAINDER NUMBER;
5 MYRESULT NUMBER :=0;
6 BEGIN
7 OperInput:=myinput;
8
9 while OperInput!=0 LOOP
10
11 MYREMAINDER:=mod(OperInput,10);
12 MYRESULT:=(MYRESULT*10)+MYREMAINDER;
13 OperInput:=TRUNC(OperInput/10);
14
15 end LOOP;
16
17 finalresult:=MYRESULT;
18
19 END;
20* /
Procedure SAMPLE_REV compiled
SQL>DECLARE
2 ENTER NUMBER;
3 finalresult NUMBER;
4 BEGIN
5 ENTER:=&ENTER;
6 SAMPLE_REV(ENTER,finalresult);
7 dbms_output.put_line('Output is '|| finalresult);
8 END;
9 /
Enter value for ENTER: 987
Output is 789
PL/SQL procedure successfully completed.
SQL>
In order to view the output of a PL/SQL procedure using dbms_ouput.put_line, run the following command in your session window:
SET SERVEROUTPUT ON;
Should do the trick :)
I see your calculation is not correct. I have added additional output in the procedure to see what it is printing.
MYRESULT itslef is empty and hence you see the output is empty.
set serveroutput on;
CREATE OR REPLACE PROCEDURE SAMPLE_REV (myinput IN NUMBER, finalresult OUT NUMBER)
IS
OperInput NUMBER;
MYREMAINDER NUMBER;
MYRESULT NUMBER;
BEGIN
OperInput:=myinput;
while OperInput!=0 LOOP
MYREMAINDER:=mod(OperInput,10);
dbms_output.put_line('remainder ' || MYREMAINDER);
dbms_output.put_line('in ' || MYRESULT);
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
dbms_output.put_line('out ' || MYRESULT);
OperInput:=TRUNC(OperInput/10);
end LOOP;
finalresult:=MYRESULT;
END;
This line is the problem:
MYRESULT:=(MYRESULT*10)+MYREMAINDER;
On the first iteration MYRESULT is null. So the MYRESULT*10 will be also null. And null + MYREMAINDER = null;
Initialize MYRESULT in the declare section to 0;
i want to add a variable to a stored procedure but i want to be able to run the stored procedure in one of 2 different ways:
- if it is null, then it runs everything otherwise just matching records
- if it is null, then make it default to a set value otherwise just matching records
var countyvar varchar2(50);
begin
if countyvar is null then 'yyyy';
end if;
end;
OR
var countyvar varchar2(50);
begin
if countyvar is null then run script for all locations;
if countyvar is 'yyyy' then run script for only that location;
end if;
end;
used here:
select locations, count(accountID) from dim_locations where location_name = :COUNTYVAR group by locations;
I don't know if this helps you, but you can use the "DEFAULT" keyword in the procedure parameter declaration. For example:
PROCEDURE Get_emp_names (Dept_num IN NUMBER DEFAULT 20)
IS ...
And then you can control the flow of your procedure from inside. Just check if "countyvar" is null or not inside the procedure.
Check this also: Default Values to Stored Procedure in Oracle
Just do this ... watch for index performance however, it may or may not perform a little slower than expected depending on your data size and such ... test it out and tune a little as needed.
select locations, count(accountID)
from dim_locations
where ( :COUNTYVAR IS NULL
OR location_name = :COUNTYVAR )
group by locations;
[[Explanation of DEFAULT option mentioned in other answer ]]
DEFAULT option only kicks in when the parameter is not provided, not when it's NULL ... here's a test sample showing the behaviour - try it out ;)
set serverout on
declare
lv_var varchar2(10);
procedure p_test ( in_parm IN varchar2 default 10 )
is
begin
dbms_output.put_line ( 'in_parm is: ' || nvl(in_parm,'<<NULL>>') );
end;
begin
p_test ( 123 );
p_test ();
p_test ( NULL );
lv_var := 234;
p_test ( lv_var );
lv_var := NULL;
p_test ( lv_var );
end;
/
in_parm is: 123
in_parm is: 10
in_parm is: <<NULL>>
in_parm is: 234
in_parm is: <<NULL>>
I am a novice to Oracle 11g and would like to view the resultset of a table output from a stored procedure. I have created the procedure and executed it. I just want to view the output in the form of a grid like in SQL Server. Please help me out.
This is the declaration of my procedure:
Spec:
TYPE ret_cursor IS REF CURSOR;
procedure get_data(
p_start_dt in varchar2,
p_end_dt in varchar2,
p_results out ret_cursor,
p_err_no out number,
p_err_msg out varchar2
);
Body:
PROCEDURE get_data(
p_start_dt IN VARCHAR2,
p_end_dt IN VARCHAR2,
p_results OUT ret_cursor,
p_err_no OUT NUMBER,
p_err_msg OUT VARCHAR2
)
IF you are using TOAD ,then its very easy to see output of refcursor .
First copy below code in Toad Editor
DECLARE
v_err_no number;
v_err_msg VARCHAR2(200);
BEGIN
get_data(
p_start_dt => SYSDATE, --depend on you
p_end_dt => SYSDATE+10, --depend on you
p_results => :ret_cursor,
p_err_no => v_err_no,
p_err_msg => v_err_msg
);
--print error message
END;
Now goto Editor-->Execute Statement f9 ,and click
Popup appear ,and asking you for ret_cursor type,select type as cursor ,do as shown below in the screenshot
Click OK ,and then you can see result in the datagrid .
If you want simply look at the result you can use SQL*Plus and it's REFCURSOR bind variable and PRINT command:
SQL> create or replace procedure p
2 (
3 x out sys_refcursor
4 )
5 is
6 begin
7 open x for select 1 a, 'a' b from dual;
8 end;
9 /
Procedure created.
SQL> var rc refcursor
SQL> exec p(:rc)
PL/SQL procedure completed.
SQL> print rc
A B
---------- -
1 a
I have a simple function where I run a stored procedure that returns a RefCursor and I try to use that RefCursor to insert data to a temporary table. I get the following error when trying to do so:
SQL Error: ORA-00947: not enough values
I know for a fact that the refcursor returns exactly the same number of values as the temporary table has, correct column names, their order and their type. I ran print RefCursor and I can see all of the data. Here's the code:
var r refcursor;
EXEC SCHEMA.PACKAGE.SPROC(:r);
insert into SCHEMA.TEMP_TABLE
values
(r);
I have to add that the stored procedure has a refcursor defined as a OUT parameter so it returns a correct type. Using print r; prints the correct data.
What am I doing wrong?
EDIT:
Based on a suggestion I tried to use a fetch to a rowtype variable, but getting Invalid Number exception whenever I attempt to fetch a row:
DECLARE
cur SYS_refcursor;
rec SCHEMA.TEMP_TABLE%rowtype;
begin
SCHEMA.PACKAGE.SPROC( cur );
LOOP
FETCH cur INTO rec;
EXIT WHEN cur%NOTFOUND;
INSERT INTO SCHEMA.TEMP_TABLE
VALUES rec;
END LOOP;
EXCEPTION
WHEN INVALID_NUMBER THEN
DBMS_output.put_line(rec.move_id);
end;
I added the exception block to see which row is failing and needless to say it is the first one. The stored procedure I run returns a refcursor of a select query from multiple tables. The temporary table defined as the exact copy of the refcursor columns and their types. Not sure what could be causing the exception.
You can't insert into a table from a refcursor. You could write a procedure that fetches from the cursor and inserts into the table. If schema.package.sproc returns a ref cursor of temp_table%rowtype, you could do something like
DECLARE
cur sys_refcursor;
rec schema.temp_table%rowtype;
BEGIN
schema.package.sproc( cur );
LOOP
FETCH cur INTO rec;
EXIT WHEN cur%NOTFOUND;
INSERT INTO schema.temp_table
VALUES rec;
END LOOP;
END;
You can use LOOP + FETCH to filter the row in SYS_REFCURSOR.
Exit the LOOP using "EXIT WHEN ref_%notfound;"
Example: Have 2 functions.
FUNCTION get_data
RETURN SYS_REFCURSOR
is
s varchar2(2000);
ref_ SYS_REFCURSOR;
begin
s := 'select username, password, email from user_info where id < 100';
OPEN ref_ FOR s;
return ref_;
end;
FUNCTION load_data_in_table
RETURN varchar2
is
s varchar2(2000);
puser_name varchar2(2000);
ppassword varchar2(2000);
pemail varchar2(2000);
ref_ SYS_REFCURSOR;
begin
ref_ := get_data();
LOOP
--process_record_statements;
FETCH ref_ into puser_name, ppassword, pemail;
s := 'INSERT INTO TEST_USER_EXP VALUES(:user_name, :password, :email)';
EXECUTE IMMEDIATE s USING puser_name, ppassword, pemail;
EXIT WHEN ref_%notfound;
END LOOP;
commit;
return 'OK';
end;