TYPE cause ORA-06502: PL/SQL: numeric or value error - plsql

I have the following PL/SQL package:
CREATE OR REPLACE PACKAGE PKG_JCSJ
AS
TYPE record_organ_cant IS RECORD(CANT_CODE VARCHAR2(90),
ORGAN_ID VARCHAR2(90) ,
CANT_NAME VARCHAR2(90),
SUPP_TYPE VARCHAR2(20));
--TYPE array_organ_cant IS TABLE of PKG_JCSJ.record_organ_cant;
TYPE array_organ_cant IS TABLE of pub_organ_cant%ROWTYPE;
function fn_transe_organ_cant return PKG_JCSJ.array_organ_cant PIPELINED;
END PKG_JCSJ;
create or replace package body PKG_JCSJ is
function fn_transe_organ_cant return PKG_JCSJ.array_organ_cant PIPELINED
as
cursor cursor_organ_cant is select * from pub_organ_cant ;
record_o_c pub_organ_cant%rowtype;
record_o_c2 pub_organ_cant%rowtype;
cant_code VARCHAR2(90);
TYPE ref_cursor IS REF CURSOR;
array_column_value ref_cursor;
sp_cant_code VARCHAR2(90);
begin
open cursor_organ_cant;
loop
fetch cursor_organ_cant into record_o_c;
exit when cursor_organ_cant%notfound;
cant_code := record_o_c.cant_code;
if instr(cant_code, ',')>0 then
open array_column_value for select * from table(fn_split(cant_code));
loop
fetch array_column_value into sp_cant_code;
exit when array_column_value%notfound;
--DBMS_OUTPUT.put_line('---' || sp_cant_code);
record_o_c2.CANT_CODE := sp_cant_code;
record_o_c2.ORGAN_ID := record_o_c.ORGAN_ID;
record_o_c2.CANT_NAME := record_o_c.CANT_NAME;
record_o_c2.SUPP_TYPE := record_o_c.SUPP_TYPE;
--DBMS_OUTPUT.put_line('++++++' || record_o_c2.CANT_CODE);
PIPE ROW (record_o_c2);
end loop;
close array_column_value;
else
PIPE ROW (record_o_c);
end if;
end loop;
close cursor_organ_cant;
return;
end fn_transe_organ_cant;
begin
null;
end PKG_JCSJ;
Why is this statement failing?
TYPE array_organ_cant IS TABLE of PKG_JCSJ.record_organ_cant;
error info is ORA-06502: PL/SQL: numeric or value error. However, when I use the following statement, success!
TYPE array_organ_cant IS TABLE of pub_organ_cant%ROWTYPE;
record_organ_cant is same structure with TABLE pub_organ_cant, I have no idea why the former fails and the latter is successful, what's the difference?
then, package body as follow,

First of all, in your package body you don't have to use PKG_JCSJ. because its declared within the pacakge and should be accessible to any of its function like
create or replace package body PKG_JCSJ is
function fn_transe_organ_cant return array_organ_cant PIPELINED
....
Next, when you declare again you don't need PKG_JCSJ. like
CREATE OR REPLACE PACKAGE PKG_JCSJ
AS
TYPE record_organ_cant IS RECORD(CANT_CODE VARCHAR2(90),
ORGAN_ID VARCHAR2(90) ,
CANT_NAME VARCHAR2(90),
SUPP_TYPE VARCHAR2(20));
TYPE array_organ_cant IS TABLE of record_organ_cant;
function fn_transe_organ_cant return array_organ_cant PIPELINED;
END PKG_JCSJ;

Related

Oracle 19C database issue

I have a package working fine in 11g version.
But when I deploy the same package in 19c version, the behavior is different.
PFB the description.
Package specification has an cursor and created a table type with cursor%rowtype.
Having a pipelined function which returns the table type.
Using the function with table clause
select * from table(function)
so that the return value can act as a table and I can read the result with column names.
In 11g, the function is returning the column headers same as the cursor column names.
But in 19c, the function is returning column headers like 'Attr_1, Attr_2, etc'.
I need the function to return the column headers as the cursor columns names.
Note: Code can't be shared as it is very sensitive.
Sample:
PFB the sample.
Create table tb_test (id number, description varchar2 (50));
create or replace package pkg_test is
cursor cur_test is
select *
from tb_test
where 1=2;
type typ_cur_test is table of cur_test%rowtype;
function fn_test(p_rows in number) return typ_cur_test pipelined;
end;
create or replace package body pkg_test is
function fn_test(p_rows in number) return typ_cur_test pipelined as
l_tab typ_cur_test := cur_typ_test();
begin
for i in 1..p_rows loop l_tab.extend;
l_tab(i).Id := i;
l_tab(i). Description := 'test';
pipe roe(l_tab(i));
end loop;
return ;
end;
end pkg_test;
Select * from table(pkg_test.fn_test(2));
In 11g, the above select gives column headers as "id, description", but in 19c i am getting as "ATTR_1, ATTR_2".
Please help.
Solution for your issue could be:
create or replace package pkg_test is
cursor cur_test is
select *
from tb_test
where 1=2;
type typ_cur_test is table of {tb_test}%rowtype;
function fn_test(p_rows in number) return typ_cur_test pipelined;
end;
Was able to reproduce the explained behavior. On 19c -> Attr_1, Attr_2 on 11 -> ID, Description
Workaround I found is use base table/view%rowtype instead of cursor%rowtype.

Expression is of wrong type when sending nested array to Function

I want to send a collection to a Function, but I keep getting an error.
I defined the RECORD and TYPES in my Package Header and Implemented the body aswell. I dont understand why I cant send a simple collection as a parameter, the idea is for me to loop through the collection and do some comparisation then return a char within a sql statement.
Been struggling with this for a week now, any help is appreciated.
Exact error:
ORA-06550: line 9, column 45:
PLS-00382: expression is of wrong type
ORA-06550: line 9, column 40:
PLS-00306: wrong number or types of arguments in call to 'TEST_F'
ORA-06550: line 9, column 23:
PL/SQL: ORA-00904: "PACKAGE_SS"."TEST_F": invalid identifier
ORA-06550: line 9, column 3:
PL/SQL: SQL Statement ignored
Header:
create or replace
PACKAGE PACKAGE_SS AS
type t_itemnumber is table of varchar2(100) index by BINARY_INTEGER;
type t_alternative_rec is record
(
itemnumber t_itemnumber
);
type t_alternative_prev is table of t_alternative_rec INDEX BY BINARY_INTEGER;
type t_procestype_rec is record
(
procestype char
);
TYPE result_table IS TABLE OF t_procestype_rec;
FUNCTION test_f(p_items_prev IN t_alternative_prev) RETURN result_table PIPELINED;
END AOPA_VALIDATE_SS;
The package body looks like this:
create or replace
PACKAGE BODY PACKAGE_SS AS
FUNCTION test_f(p_items_prev IN t_alternative_prev) RETURN result_table PIPELINED IS
processType char(1) := 'U';
rec t_procestype_rec :=null;
BEGIN
DBMS_OUTPUT.PUT_LINE('ENTERD ');
if (processType= 'U') then
select 'U' into rec from dual;
end if;
if (processType='C') then
select 'C' into rec from dual;
end if;
if (processType='D') then
select 'D' into rec from dual;
end if;
pipe row (rec);
return;
END test_f;
END PACKAGE_SS;
Usage plsql script:
DECLARE
prev_rev_alternatives PACKAGE_SS.t_alternative_prev;
BEGIN
prev_rev_alternatives(1).itemnumber(10) := 'PR454545';
prev_rev_alternatives(1).itemnumber(20) := 'PR333333';
SELECT * FROM table(PACKAGE_SS.test_f(prev_rev_alternatives));
END;
There are two things which my eyes fall upon:
Usage of SELECT without INTO in an anonymous PLSQL block is not supposed to work.
Usage of types in an SQL statement requires the type defined as an object, not within a package specification.
Try
CREATE TYPE
https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_8001.htm
and
SELECT * INTO ... FROM ...
This might help.

plsql Result consisted of more than one row. How to handel it

CREATE PROCEDURE book_check(book_Id varchar(64))
begin
declare book_available varchar(64);
select book_id into book_available
from book_copies
where No_of_Copies >0 and book_id=book_Id;
if(book_Id in book_available ) then
select concat ("Book available");
else
select concat ("Book not available");
end if;
end
//
what can i write in place of 'in' . I know the syntax i wrong .
It's easy - try something like this:
create or replace function book_check(book_id varchar) return varchar as
begin
for r in (select 1 from book_copies where no_of_copies > 0 and book_id = book_check.book_id) loop
return 'Book available';
end loop;
return 'Book not available';
end book_check;
/
It's unclear to me what you are trying to do. I assume you want to find out if a book is available or not and return that information to the caller of the function.
Your declaration of the procedure header and the variables is wrong.
Procedure or function parameters are not defined with a length for the datatype.
Inside a procedure or function you don't need declare
you can't have a select statement without putting the result somewhere. * Assigning a constant value to a variable is done using :=
If you want to return information to the caller, use a function, not a procedure
You should not give variables or parameters the same name as a column. A common naming convention in the Oracle world is to give parameters the prefix p_ and local variables the prefix l_ but anything that avoids a name clash between column names and variables is OK - just be consistent.
CREATE function book_check(p_book_id varchar)
return varchar
as
l_count integer;
l_result varchar(20);
begin
select count(*)
into l_count
from book_copies
where No_of_Copies > 0
and book_id = p_book_id;
if l_count > 0 then
l_result := 'Book available';
else
l_result := "Book not available";
end if;
return result;
end;
/
You should really take the time and read the PL/SQL Language reference. All the above is explained there.

retrieve recordset with more than one column value using refcursor in oracle

am creating a package in pl/sql . with in this i declared the ref cursor . With in procedure am using select statement with multiple column name . but am not able to get the result.
here i attached my code. Help me to correct the error. Am new to pl/sql
code
CREATE OR REPLACE PACKAGE types AS
TYPE cursor_type IS REF CURSOR;
END Types;
/
CREATE OR REPLACE
PROCEDURE get_CDR_rs (p_no IN zkv.FLD_callingPartyNumber%TYPE,
CDR_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN CDR_recordset FOR
SELECT FLD_callingPartyNumber,
FLD_dateTimeConnect
FROM CISCOCUIC_TBL
WHERE FLD_callingPartyNumber= p_no
ORDER BY FLD_callingPartyNumber,;
END get_CDR_rs;
/
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
l_cursor SYS_REFCURSOR;
l_callingPartyNumber zkv.FLD_callingPartyNumber%TYPE;
l_dateTimeConnect zkv.FLD_dateTimeConnect%TYPE;
BEGIN
LOOP
FETCH l_cursor
INTO l_callingPartyNumber, l_dateTimeConnect;
EXIT WHEN l_cursor%NOTFOUND;
END LOOP;
CLOSE l_cursor;
END;
/
Error
9/41 PL/SQL: ORA-00936: missing expression
5/5 PL/SQL: SQL Statement ignored
First thing is there is a syntax error in the procedure. It should be
CREATE OR REPLACE
PROCEDURE get_CDR_rs (p_no IN zkv.FLD_callingPartyNumber%TYPE,
CDR_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN CDR_recordset FOR
SELECT FLD_callingPartyNumber,
FLD_dateTimeConnect
FROM CISCOCUIC_TBL
WHERE FLD_callingPartyNumber= p_no
ORDER BY FLD_callingPartyNumber; -- there was a comma which is not required or you
-- missed a column
END get_CDR_rs;
/
Secondly where is get_CDR_rs being called to retrieve the results?
Thirdly why do you need the following? because you are using sys_refcursor
CREATE OR REPLACE PACKAGE types AS
TYPE cursor_type IS REF CURSOR;
END Types;
/
If you would like to see the results of your procedure which returns sys_refcursor, do as follows
variable rset refcursor;
DECLARE
p_no zkv.FLD_callingPartyNumber%TYPE;
BEGIN
p_no := '123';
get_CDR_rs (p_no, :rset);
END;
/
print rset

How to call PL/SQL function in side a trigger

I am new to pl/sql. can any one tell me how to call pl/sql function inside a trigger.
I tired it but it gives an error when i try to run it.
DROP TRIGGER INTF_CONTROLLER_TREXE;
CREATE OR REPLACE TRIGGER INTF_CONTROLLER_TREXE
before insert ON INTF_CONTROLLER for each row
begin
BACKOFFICE_UPDATE();
end;
CREATE OR REPLACE FUNCTION BACKOFFICE_UPDATE
RETURN NUMBER IS
tmpVar NUMBER;
BEGIN
tmpVar := 0;
DBMS_OUTPUT.put_line ('HELLO');
RETURN tmpVar;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END BACKOFFICE_UPDATE;
I tried to run it using TOAD. it gives the following error
PLS-00221: 'BACKOFFICE_UPDATE' is not a procedure or is undefined
You need to store the result of your function call in a local variable
For example:
CREATE OR REPLACE TRIGGER INTF_CONTROLLER_TREXE
before insert ON INTF_CONTROLLER for each row
declare
dummy NUMBER;
begin
dummy := BACKOFFICE_UPDATE();
end;

Resources