PL/SQL Function return custom type exception - oracle

I have created a package which holds a custom type and a function that returns the custom type as below;
create or replace
PACKAGE INHOUSE_CUST_API
AS
TYPE doc_rec
IS
RECORD
(
doc_Title doc_issue_reference.title%Type,
doc_Number DOC_ISSUE_REFERENCE.DOC_NO%TYPE,
doc_Type DOC_ISSUE_REFERENCE.FILE_TYPE%TYPE,
doc_FileName DOC_ISSUE_REFERENCE.FILE_NAME%TYPE,
doc_Path DOC_ISSUE_REFERENCE.PATH%TYPE);
FUNCTION Get_Budget_Doc(
company IN VARCHAR2,
budget_process_id IN VARCHAR2,
budget_ptemplate_id IN VARCHAR2)
RETURN doc_rec;
END INHOUSE_CUST_API;
after that, I created the body of the function as below
create or replace
PACKAGE BODY INHOUSE_CUST_API
AS
FUNCTION Get_Budget_Doc(
company IN VARCHAR2,
budget_process_id IN VARCHAR2,
budget_ptemplate_id IN VARCHAR2)
RETURN doc_rec
IS
enhDocItem ENHANCED_DOC_REFERENCE_OBJECT%ROWTYPE;
docIssueRef DOC_ISSUE_REFERENCE%ROWTYPE;
docKeyValue VARCHAR2(150);
docIssueRef_rec doc_rec;
BEGIN
docKeyValue := company||'^'||budget_process_id||'^'||budget_ptemplate_id||'^';
--dbms_output.put_line(docKeyValue);
SELECT *
INTO enhDocItem
FROM ENHANCED_DOC_REFERENCE_OBJECT
WHERE KEY_VALUE= docKeyValue;
SELECT *
INTO docIssueRef
FROM DOC_ISSUE_REFERENCE
WHERE DOC_NO = enhDocItem.DOC_NO;
docIssueRef_rec.doc_Title :=docIssueRef.Title;
docIssueRef_rec.doc_Number:=docIssueRef.DOC_NO;
docIssueRef_rec.doc_Type :=docIssueRef.FILE_TYPE;
docIssueRef_rec.doc_Path :=docIssueRef.PATH;
RETURN docIssueRef_rec;
END Get_Budget_Doc;
END INHOUSE_CUST_API;
when I try to call the function as like
select INHOUSE_CUST_API.Get_Budget_Doc('param1','param2','param3') from dual;
I receive this exception
ORA-00902: invalid datatype
00902. 00000 - "invalid datatype"
*Cause:
*Action:
any help is appreciated.

You might want to use a table function to return your custom type. Here is a very simple example:
CREATE OR REPLACE PACKAGE brianl.deleteme AS
TYPE doc_rec_t IS RECORD
(
name VARCHAR2( 10 )
, age NUMBER( 3 )
);
TYPE doc_rec_tt IS TABLE OF doc_rec_t;
FUNCTION age( p_name IN VARCHAR2, p_age IN NUMBER, p_years IN INTEGER )
RETURN doc_rec_tt
PIPELINED;
END deleteme;
CREATE OR REPLACE PACKAGE BODY brianl.deleteme AS
FUNCTION age( p_name IN VARCHAR2, p_age IN NUMBER, p_years IN INTEGER )
RETURN doc_rec_tt
PIPELINED AS
l_ret doc_rec_t;
BEGIN
l_ret.name := p_name;
l_ret.age := p_age;
FOR i IN 1 .. p_years
LOOP
PIPE ROW (l_ret);
l_ret.age := l_ret.age + 1;
END LOOP;
END age;
END deleteme;
Invoke as follows:
SELECT * FROM TABLE( brianl.deleteme.age( 'Brian', 67, 3 ) );
The results:
NAME AGE
Brian 67
Brian 68
Brian 69

a SELECT statement in direct mode cann't return a complex data type like a record.

Related

Method call ends with error ORA-04063 + ORA-06512

I have such objects and methods:
create or replace type PolicyType as object(
policy_id number,
policy_nr varchar2(20),
price number) NOT FINAL;
/
create or replace type TravelerType as object(
first_name varchar2(30),
last_name varchar2(30),
pers_code varchar2(12));
/
create or replace type TravelersType as table of TravelerType;
/
create or replace type ref_TargetPlaceType as object (
target_code varchar2(4),
description varchar2(30));
/
create or replace type TravelPolicyType under PolicyType (
target_code REF ref_TargetPlaceType,
traveler_data TravelersType,
MEMBER FUNCTION getTraveler (p_code IN varchar2) RETURN TravelerType,
MEMBER PROCEDURE addTraveler( traveler IN TravelerType ));
/
CREATE OR REPLACE TYPE BODY TravelPolicyType AS
MEMBER FUNCTION getTraveler(p_code IN varchar2) RETURN TravelerType AS
BEGIN
for i in 1 .. self.traveler_data.count() loop
if( self.traveler_data(i).pers_code = p_code )
then
return self.traveler_data(i);
end if;
end loop;
END;
MEMBER PROCEDURE addTraveler(traveler IN TravelerType) AS
BEGIN
self.traveler_data.extend();
self.traveler_data(self.traveler_data.count) :=traveler;
END;
END;
I am tying to call methods, bet getting error for both
ORA-04063: type body "SQL_LPZCXWDSKRAXJUEWPMXNUMWYH.TRAVELPOLICYTYPE" has errors ORA-06512:
declare
policy_d TravelPolicyType;
traveler TravelerType;
begin
select value(a) into policy_d from travel_policies a where a.policy_nr='TP00000000003';
traveler:=policy_d.getTraveler('050976-12568');
end;
declare
policy_d TravelPolicyType;
new_traveler TravelerType;
begin
select value(a) into policy_d from travel_policies a where a.policy_nr='TP00000000003';
new_traveler:=TravelerType('Test','Traveler', '123456-44444');
policy_d.addTraveler(new_traveler);
end;
Can not understand what I am doing wrongly. Please help with advise
See what errors are reported in that object:
select * from user_errors;
NAME
TYPE
SEQUENCE
LINE
POSITION
TEXT
ATTRIBUTE
MESSAGE_NUMBER
TRAVELPOLICYTYPE
TYPE BODY
1
4
22
PLS-00302: component 'TRAVELERS_DATA' must be declared
ERROR
302
TRAVELPOLICYTYPE
TYPE BODY
2
4
3
PL/SQL: Statement ignored
ERROR
0
Your type has traveler_data, but the body refers to travelers_data. You need to make that naming consistent.

PL/SQL Function Return View RowType internal exception

I have the below function which compiles. DOC_ISSUE_REFERENCE STANDS for a VIEW
CREATE OR REPLACE
PACKAGE BODY INHOUSE_CUST_API
AS
FUNCTION Get_Budget_Doc(
company IN VARCHAR2,
budget_process_id IN VARCHAR2,
budget_ptemplate_id IN VARCHAR2)
RETURN DOC_ISSUE_REFERENCE%ROWTYPE
IS
enhDocItem ENHANCED_DOC_REFERENCE_OBJECT%ROWTYPE;
docKeyValue VARCHAR2(150);
docIssueRef DOC_ISSUE_REFERENCE%ROWTYPE;
BEGIN
docKeyValue := company||'^'||budget_process_id||'^'||budget_ptemplate_id||'^';
-- dbms_output.put_line(docKeyValue);
SELECT *
INTO enhDocItem
FROM ENHANCED_DOC_REFERENCE_OBJECT
WHERE KEY_VALUE= docKeyValue;
SELECT *
INTO docIssueRef
FROM DOC_ISSUE_REFERENCE
WHERE DOC_NO = enhDocItem.DOC_NO;
RETURN docIssueRef;
END Get_Budget_Doc;
END INHOUSE_CUST_API;
the point here that when I call the function I receive
ORA-06553: PLS-801: internal error [55018]
06553. 00000 - "PLS-%s: %s"
*Cause:
*Action:
which does not show any thing or help. I am sure that both selects return 1 row only. any help is appreciated
this is my solution depending on Ilia Maskov comment
the package is
create or replace
PACKAGE INHOUSE_CUST_API
AS
TYPE doc_rec
IS
RECORD
(
doc_Title doc_issue_reference.title%Type,
doc_Number DOC_ISSUE_REFERENCE.DOC_NO%TYPE,
doc_Type DOC_ISSUE_REFERENCE.FILE_TYPE%TYPE,
doc_FileName DOC_ISSUE_REFERENCE.FILE_NAME%TYPE,
doc_Path DOC_ISSUE_REFERENCE.PATH%TYPE);
TYPE doc_rec_tab IS TABLE OF doc_rec;
FUNCTION Get_Budget_Doc(
company IN VARCHAR2,
budget_process_id IN VARCHAR2,
budget_ptemplate_id IN VARCHAR2)
RETURN doc_rec_tab PIPELINED;
END INHOUSE_CUST_API;
and the body is
create or replace
PACKAGE BODY INHOUSE_CUST_API
AS
FUNCTION Get_Budget_Doc(
company IN VARCHAR2,
budget_process_id IN VARCHAR2,
budget_ptemplate_id IN VARCHAR2)
RETURN doc_rec_tab PIPELINED
IS
enhDocItem ENHANCED_DOC_REFERENCE_OBJECT%ROWTYPE;
-- docIssueRef DOC_ISSUE_REFERENCE%ROWTYPE;
docKeyValue ENHANCED_DOC_REFERENCE_OBJECT.KEY_VALUE%TYPE;
docIssueRef_rec doc_rec;
docTable doc_rec_tab;
BEGIN
docKeyValue := company||'^'||budget_process_id||'^'||budget_ptemplate_id||'^';
<<outer_loop>>
FOR doc_no_rec IN (SELECT DOC_NO FROM ENHANCED_DOC_REFERENCE_OBJECT WHERE KEY_VALUE= docKeyValue) LOOP
--dbms_output.put_line(doc_no_rec.rownum);
<<inner_loop>>
FOR rec_ IN(SELECT Title, DOC_NO,FILE_TYPE,FILE_NAME,PATH FROM DOC_ISSUE_REFERENCE WHERE DOC_NO = doc_no_rec.DOC_NO) LOOP
PIPE row(rec_);
END LOOP inner_loop;
END LOOP outer_loop;
RETURN;
END Get_Budget_Doc;
END INHOUSE_CUST_API;

ORA-00902 for function that returns a table [duplicate]

I am writing a function and i want to wrap it with table function so i can use with select query.
Here is my type declaration and the some lines of my functions
CREATE OR REPLACE PACKAGE TYPES
AS
TYPE CURSORTYPE IS REF CURSOR;
TYPE vbugsrec
IS
RECORD (
bug_id bugs.bug_id%TYPE,
facility bugs.facility%TYPE
);
TYPE vbugstable
IS
TABLE OF vbugsrec
INDEX BY BINARY_INTEGER;
END;
/
CREATE OR REPLACE PACKAGE BODY CustomQueries
AS
FUNCTION pendverifylist (myldapid IN userpass.ldapalias%TYPE,
maxrows IN PLS_INTEGER:= CustomQueries.maxrecords)
RETURN types.vbugstable
IS
datarows types.vbugstable;
var_useralias userpass.ldapalias%TYPE
:= UPPER (pendverifylist.myldapid) ;
CURSOR pendverify_cur (
cursor_var_alias IN userpass.ldapalias%TYPE,
cursor_var_mybugstatus IN bugs.bug_status%TYPE,
cursor_var_wild IN qa_list.component%TYPE
)
IS
SELECT buglist.bug_id, buglist.facility
FROM bugs buglist,
(SELECT qa.product, qa.component
FROM qa_list qa, userpass UP
WHERE qa.qa_id = UP.userid
AND UP.ldapalias = cursor_var_alias) plist
WHERE buglist.bug_status = cursor_var_mybugstatus
AND buglist.smr_state IN (SELECT fs.finalstate
FROM finalstates fs)
AND buglist.facility = plist.product
AND (buglist.product LIKE plist.component
OR plist.component = cursor_var_wild);
BEGIN
OPEN pendverifylist.pendverify_cur (cursor_var_alias => pendverifylist.var_useralias,
cursor_var_mybugstatus => CustomQueries.default_bugstatus,
cursor_var_wild => CustomQueries.wildcard);
FETCH pendverifylist.pendverify_cur
BULK COLLECT INTO pendverifylist.datarows
LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
CustomQueries.MAXRECORDS);
CLOSE pendverifylist.pendverify_cur;
RETURN pendverifylist.datarows;
END pendverifylist;
END CustomQueries;
/
When i want to use TABLE function like below, i get error.ORA-00902: invalid datatype
SELECT * FROM TABLE(CUSTOMQUERIES.PENDVERIFYLIST ( 'product', 50 ));
Can anyone please help what i am doing wrong here?
Thanks in advance
You're trying to use package-level types in plain SQL, which isn't allowed. The types declared in the package are not visible to or valid outside PL/SQL (or even in plain SQL statements within PL/SQL). A cut-down version of what you're doing:
create or replace package types as
type my_rec_type is record (dummy dual.dummy%type);
type my_table_type is table of my_rec_type index by binary_integer;
end types;
/
create or replace package p42 as
function get_table return types.my_table_type;
end p42;
/
create or replace package body p42 as
function get_table return types.my_table_type is
my_table types.my_table_type;
begin
select * bulk collect into my_table from dual;
return my_table;
end get_table;
end p42;
/
select * from table(p42.get_table);
SQL Error: ORA-00902: invalid datatype
Even within the package, if you had a procedure that tried to use the table function it would error. If you added:
procedure test_proc is
begin
for r in (select * from table(get_table)) loop
null;
end loop;
end test_proc;
... the package body compilation would fail with ORA-22905: cannot access rows from a non-nested table item.
You need to declare the types at schema level, not in a package, so using the SQL create type command:
create type my_obj_type is object (dummy varchar2(1));
/
create type my_table_type is table of my_obj_type;
/
create or replace package p42 as
function get_table return my_table_type;
end p42;
/
create or replace package body p42 as
function get_table return my_table_type is
my_table my_table_type;
begin
select my_obj_type(dummy) bulk collect into my_table from dual;
return my_table;
end get_table;
end p42;
/
select * from table(p42.get_table);
DUMMY
-----
X
Actually tehere is not need to have types in schema level. All you need to do is to define function as PIPELINED.
-- DEFINITION IN PCKG HEADER
create or replace PACKAGE "AAA" IS
TYPE t_record IS RECORD (
aaa VARCHAR(20 CHAR),
bbb VARCHAR(50 CHAR),
ccc VARCHAR(10 CHAR)
);
TYPE t_collection is table of t_record;
FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED;
END AAA;
-- PCKG BODY
create or replace PACKAGE BODY AAA AS
FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED AS
CURSOR k1 is SELECT aaa,bbb,ccc FROM table;
BEGIN
FOR rec IN k1
LOOP
pipe row( (rec) );
END LOOP;
END get_records
END AAA;
-- CALLING FUNCTION OUTSIDE OF PCKG
select * from TABLE(AAA.get_records(par1, par2));
Thanks to Alex Poole. This is what i ended up with
CREATE OR REPLACE TYPE vbugsrec
IS
OBJECT (
bug_id NUMBER(9),
facility VARCHAR2(256)
);
CREATE OR REPLACE TYPE vbugstable
IS
TABLE OF vbugsrec;
/
CREATE OR REPLACE PACKAGE BODY CustomQueries
AS
FUNCTION pendverifylist (myldapid IN userpass.ldapalias%TYPE,
maxrows IN PLS_INTEGER:= CustomQueries.maxrecords)
RETURN vbugstable
IS
datarows vbugstable := vbugstable();
var_useralias userpass.ldapalias%TYPE:= UPPER (pendverifylist.myldapid) ;
TYPE temp_rec IS RECORD (
bug_id bugs.bug_id%TYPE,
facility bugs.facility%TYPE
);
TYPE temp_records
IS
TABLE OF temp_rec
INDEX BY BINARY_INTEGER;
temporary_records temp_records;
CURSOR pendverify_cur (
cursor_var_alias IN userpass.ldapalias%TYPE,
cursor_var_mybugstatus IN bugs.bug_status%TYPE,
cursor_var_wild IN qa_list.component%TYPE
)
IS
SELECT buglist.bug_id, buglist.facility
FROM bugs buglist,
(SELECT qa.product, qa.component
FROM qa_list qa, userpass UP
WHERE qa.qa_id = UP.userid
AND UP.ldapalias = cursor_var_alias) plist
WHERE buglist.bug_status = cursor_var_mybugstatus
AND buglist.smr_state IN (SELECT fs.finalstate
FROM finalstates fs)
AND buglist.facility = plist.product
AND (buglist.product LIKE plist.component
OR plist.component = cursor_var_wild);
BEGIN
OPEN pendverifylist.pendverify_cur (cursor_var_alias => pendverifylist.var_useralias,
cursor_var_mybugstatus => CustomQueries.default_bugstatus,
cursor_var_wild => CustomQueries.wildcard);
FETCH pendverifylist.pendverify_cur
BULK COLLECT INTO temporary_records
LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
CustomQueries.MAXRECORDS);
CLOSE pendverifylist.pendverify_cur;
IF temporary_records.COUNT <> 0
THEN
FOR rec_idx IN temporary_records.FIRST .. temporary_records.LAST
LOOP
datarows.EXTEND;
datarows (datarows.LAST) :=
vbugsrec (temporary_records (rec_idx).bug_id,
temporary_records (rec_idx).facility);
END LOOP;
END IF;
RETURN pendverifylist.datarows;
END pendverifylist;
END CustomQueries;
/

In plsql how can a function use an object declared in a package

i have a package(that is in beta, just want to make it work):
CREATE OR REPLACE PACKAGE pkg1 AS
type pipeDefinition is record
(
str VARCHAR2(4000),
num NUMBER,
);
type pipeContainer is table of pipeDefinition;
FUNCTION f1(x NUMBER) RETURN
pipeContainer pipelined;
END pkg1;
and the package body
CREATE PACKAGE BODY pkg1 AS
FUNCTION f1(x NUMBER) RETURN
pipeContainer pipelined
IS
BEGIN
FOR i IN 1..x LOOP
PIPE ROW(pipeDefinition('i',i));
END LOOP;
RETURN;
END f1;
END pkg1;
my problems:
1if i try to run the above i get
"error at line:
PIPE ROW(pipeDefinition('i',i));
function pipeDefinition can not be found" (not exactly exactly what it said, but close)
2if i try to use pkg1.pipeDefinition instead i get the same error
"error at line:
PIPE ROW(pipeDefinition('i',i));
function pipeDefinition can not be found"
3if i try to add
type pipeDefinition is record
(
str VARCHAR2(4000),
num NUMBER,
);
type pipeContainer is table of pipeDefinition;
in the package body, it sais
"can not declare more than 1 pipeContainer
and more than 1 pipeDefinition"
4if i try to add
type pipeDefinition2 is record
(
str VARCHAR2(4000),
num NUMBER,
);
type pipeContainer2 is table of pipeDefinition2;
in the package body(and alter the pipeRow line with pipeDefinition2), it sais
"the object referenced is of a diferent kind as to the one the function is suposed to output"
5if i try to add 4 and make the function return pipeContainer2 pipelined it sais
"function mismatch package and body"
6if i try to add 6 and make function return pipeContainer2 pipelined in the package also i get
"pipeContainer2 not defined before using it " in the package creator
can anyone give me some hints?
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Klas Lindbäck, you are my hero!
Solution:
CREATE OR REPLACE PACKAGE pkg1 AS
type pipeDefinition is record
(
str VARCHAR2(4000),
num NUMBER,
);
type pipeContainer is table of pipeDefinition;
FUNCTION f1(x NUMBER) RETURN
pipeContainer pipelined;
END pkg1;
and the package body
CREATE PACKAGE BODY pkg1 AS
FUNCTION f1(x NUMBER) RETURN
outrec1 pipeDefinition;
--removed: pipeContainer pipelined
IS
BEGIN
FOR i IN 1..x LOOP
--removed: PIPE ROW(pipeDefinition('i',i));
--newLines:
outrec1.str := 'a';
outrec1.num := i;
PIPE ROW(outrec1);
--endNewLines.
END LOOP;
RETURN;
END f1;
END pkg1;
and my new pointer function is finally complete! :"D
SELECT * FROM TABLE(pkg1.f1(5));
|str | num|
a | 1
a | 2
a | 3
a | 4
a | 5
Create or replace package pk2 as
type c1 is ref cursor return employees%rowtype;
type outrec is record (
var_num number,
var1 varchar2(50),
var2 varchar2(50));
type outrecset is table of outrec;
function f_trans (c2 c1) return outrecset pipelined;
end pk2;
create or replace package body pk2 as
function f_trans(c2 c1) return outrecset pipelined is
outrec1 outrec;
outrec2 c2%rowtype;
begin
loop
fetch c2 into outrec2;
exit when c2%notfound;
outrec1.var_num := outrec2.employee_id;
outrec1.var1 := outrec2.first_name;
outrec1.var2 := outrec2.last_name;
PIPE ROW(outrec1);
outrec1.var1 := outrec2.email;
outrec1.var2 := outrec2.phone_number;
PIPE ROW(outrec1);
END LOOP;
RETURN;
END f_trans;
END pk2;
please take hint from this code
data type for the record is not declared

Table function with bulk collection throws invalid datatype

I am writing a function and i want to wrap it with table function so i can use with select query.
Here is my type declaration and the some lines of my functions
CREATE OR REPLACE PACKAGE TYPES
AS
TYPE CURSORTYPE IS REF CURSOR;
TYPE vbugsrec
IS
RECORD (
bug_id bugs.bug_id%TYPE,
facility bugs.facility%TYPE
);
TYPE vbugstable
IS
TABLE OF vbugsrec
INDEX BY BINARY_INTEGER;
END;
/
CREATE OR REPLACE PACKAGE BODY CustomQueries
AS
FUNCTION pendverifylist (myldapid IN userpass.ldapalias%TYPE,
maxrows IN PLS_INTEGER:= CustomQueries.maxrecords)
RETURN types.vbugstable
IS
datarows types.vbugstable;
var_useralias userpass.ldapalias%TYPE
:= UPPER (pendverifylist.myldapid) ;
CURSOR pendverify_cur (
cursor_var_alias IN userpass.ldapalias%TYPE,
cursor_var_mybugstatus IN bugs.bug_status%TYPE,
cursor_var_wild IN qa_list.component%TYPE
)
IS
SELECT buglist.bug_id, buglist.facility
FROM bugs buglist,
(SELECT qa.product, qa.component
FROM qa_list qa, userpass UP
WHERE qa.qa_id = UP.userid
AND UP.ldapalias = cursor_var_alias) plist
WHERE buglist.bug_status = cursor_var_mybugstatus
AND buglist.smr_state IN (SELECT fs.finalstate
FROM finalstates fs)
AND buglist.facility = plist.product
AND (buglist.product LIKE plist.component
OR plist.component = cursor_var_wild);
BEGIN
OPEN pendverifylist.pendverify_cur (cursor_var_alias => pendverifylist.var_useralias,
cursor_var_mybugstatus => CustomQueries.default_bugstatus,
cursor_var_wild => CustomQueries.wildcard);
FETCH pendverifylist.pendverify_cur
BULK COLLECT INTO pendverifylist.datarows
LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
CustomQueries.MAXRECORDS);
CLOSE pendverifylist.pendverify_cur;
RETURN pendverifylist.datarows;
END pendverifylist;
END CustomQueries;
/
When i want to use TABLE function like below, i get error.ORA-00902: invalid datatype
SELECT * FROM TABLE(CUSTOMQUERIES.PENDVERIFYLIST ( 'product', 50 ));
Can anyone please help what i am doing wrong here?
Thanks in advance
You're trying to use package-level types in plain SQL, which isn't allowed. The types declared in the package are not visible to or valid outside PL/SQL (or even in plain SQL statements within PL/SQL). A cut-down version of what you're doing:
create or replace package types as
type my_rec_type is record (dummy dual.dummy%type);
type my_table_type is table of my_rec_type index by binary_integer;
end types;
/
create or replace package p42 as
function get_table return types.my_table_type;
end p42;
/
create or replace package body p42 as
function get_table return types.my_table_type is
my_table types.my_table_type;
begin
select * bulk collect into my_table from dual;
return my_table;
end get_table;
end p42;
/
select * from table(p42.get_table);
SQL Error: ORA-00902: invalid datatype
Even within the package, if you had a procedure that tried to use the table function it would error. If you added:
procedure test_proc is
begin
for r in (select * from table(get_table)) loop
null;
end loop;
end test_proc;
... the package body compilation would fail with ORA-22905: cannot access rows from a non-nested table item.
You need to declare the types at schema level, not in a package, so using the SQL create type command:
create type my_obj_type is object (dummy varchar2(1));
/
create type my_table_type is table of my_obj_type;
/
create or replace package p42 as
function get_table return my_table_type;
end p42;
/
create or replace package body p42 as
function get_table return my_table_type is
my_table my_table_type;
begin
select my_obj_type(dummy) bulk collect into my_table from dual;
return my_table;
end get_table;
end p42;
/
select * from table(p42.get_table);
DUMMY
-----
X
Actually tehere is not need to have types in schema level. All you need to do is to define function as PIPELINED.
-- DEFINITION IN PCKG HEADER
create or replace PACKAGE "AAA" IS
TYPE t_record IS RECORD (
aaa VARCHAR(20 CHAR),
bbb VARCHAR(50 CHAR),
ccc VARCHAR(10 CHAR)
);
TYPE t_collection is table of t_record;
FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED;
END AAA;
-- PCKG BODY
create or replace PACKAGE BODY AAA AS
FUNCTION get_records(p_in1 DATE, p_in2 DATE) RETURN t_collection PIPELINED AS
CURSOR k1 is SELECT aaa,bbb,ccc FROM table;
BEGIN
FOR rec IN k1
LOOP
pipe row( (rec) );
END LOOP;
END get_records
END AAA;
-- CALLING FUNCTION OUTSIDE OF PCKG
select * from TABLE(AAA.get_records(par1, par2));
Thanks to Alex Poole. This is what i ended up with
CREATE OR REPLACE TYPE vbugsrec
IS
OBJECT (
bug_id NUMBER(9),
facility VARCHAR2(256)
);
CREATE OR REPLACE TYPE vbugstable
IS
TABLE OF vbugsrec;
/
CREATE OR REPLACE PACKAGE BODY CustomQueries
AS
FUNCTION pendverifylist (myldapid IN userpass.ldapalias%TYPE,
maxrows IN PLS_INTEGER:= CustomQueries.maxrecords)
RETURN vbugstable
IS
datarows vbugstable := vbugstable();
var_useralias userpass.ldapalias%TYPE:= UPPER (pendverifylist.myldapid) ;
TYPE temp_rec IS RECORD (
bug_id bugs.bug_id%TYPE,
facility bugs.facility%TYPE
);
TYPE temp_records
IS
TABLE OF temp_rec
INDEX BY BINARY_INTEGER;
temporary_records temp_records;
CURSOR pendverify_cur (
cursor_var_alias IN userpass.ldapalias%TYPE,
cursor_var_mybugstatus IN bugs.bug_status%TYPE,
cursor_var_wild IN qa_list.component%TYPE
)
IS
SELECT buglist.bug_id, buglist.facility
FROM bugs buglist,
(SELECT qa.product, qa.component
FROM qa_list qa, userpass UP
WHERE qa.qa_id = UP.userid
AND UP.ldapalias = cursor_var_alias) plist
WHERE buglist.bug_status = cursor_var_mybugstatus
AND buglist.smr_state IN (SELECT fs.finalstate
FROM finalstates fs)
AND buglist.facility = plist.product
AND (buglist.product LIKE plist.component
OR plist.component = cursor_var_wild);
BEGIN
OPEN pendverifylist.pendverify_cur (cursor_var_alias => pendverifylist.var_useralias,
cursor_var_mybugstatus => CustomQueries.default_bugstatus,
cursor_var_wild => CustomQueries.wildcard);
FETCH pendverifylist.pendverify_cur
BULK COLLECT INTO temporary_records
LIMIT LEAST (GREATEST (0, pendverifylist.maxrows),
CustomQueries.MAXRECORDS);
CLOSE pendverifylist.pendverify_cur;
IF temporary_records.COUNT <> 0
THEN
FOR rec_idx IN temporary_records.FIRST .. temporary_records.LAST
LOOP
datarows.EXTEND;
datarows (datarows.LAST) :=
vbugsrec (temporary_records (rec_idx).bug_id,
temporary_records (rec_idx).facility);
END LOOP;
END IF;
RETURN pendverifylist.datarows;
END pendverifylist;
END CustomQueries;
/

Resources