THE LOOKUPS_FN AND MAPPINGS_FN EXAMPLE RE-WRITTEN TO RETURN SCHEMA-LEVEL -- TYPES
Since the query syntax for an object table is rather verbose, we recap it here using a table.
create type lookup_row as object ( idx number, text varchar2(20) ); / create table t of lookup_row; insert into t values ( lookup_row ( 1, 'one' ) ); insert into t values ( lookup_row ( 2, 'TWO' ) ); insert into t values ( lookup_row ( 3, 'three' ) ); insert into t values ( lookup_row ( 4, 'FOUR' ) ); insert into t values ( lookup_row ( 5, 'five' ) ); insert into t values ( lookup_row ( 6, 'SIX' ) ); insert into t values ( lookup_row ( 7, 'seven' ) ); insert into t values ( lookup_row ( 8, 'other' ) ); insert into t values ( lookup_row ( 9, 'other' ) ); insert into t values ( lookup_row ( 10, 'other' ) ); commit;
/* this is how an object query should be written */ select VALUE(a) rec from t a;
/* because its verbose, its convenient to define a view */ create or replace view v as select value(a) rec from t a;
/* test the view */ select * from v;
Now the example proper...
create type lookups_tab as table of lookup_row;
create or replace function Lookups_Fn
return lookups_tab
pipelined
is
v_row lookup_row;
begin
for j in 1..10
loop
v_row :=
case j
when 1 then lookup_row ( 1, 'one' )
when 2 then lookup_row ( 2, 'TWO' )
when 3 then lookup_row ( 3, 'three' )
when 4 then lookup_row ( 4, 'FOUR' )
when 5 then lookup_row ( 5, 'five' )
when 6 then lookup_row ( 6, 'SIX' )
when 7 then lookup_row ( 7, 'seven' )
else lookup_row ( j, 'other' )
end;
pipe row ( v_row );
end loop;
return;
end Lookups_Fn;
Note the syntax of the query. Since the table function returns an object,
it follows from the
syntax against an object table above. Again, its convenient to encapsulate
it in a view.
select value(a) rec
from table
(
cast ( Lookups_Fn() as lookups_tab )
) a;
create or replace view lookups as
select value(a) rec
from table
(
cast ( Lookups_Fn() as lookups_tab )
) a;
select * from lookups;
create or replace function Mappings_Fn ( p_input_rows in sys_refcursor )
return lookups_tab
pipelined
is
v_in_row lookup_row;
/* always initialize an object type using a type constructor
or user defined constructor */
v_out_row lookup_row := lookup_row( 1, 'x' );
begin
loop
fetch p_input_rows into v_in_row;
exit when p_input_rows%notfound;
case v_in_row.idx
when 1 then v_out_row.idx := 1*2; v_out_row.text := 'was one';
when 2 then v_out_row.idx := 2*3; v_out_row.text := 'was TWO';
when 3 then v_out_row.idx := 3*4; v_out_row.text := 'was three';
when 4 then v_out_row.idx := 4*5; v_out_row.text := 'was FOUR';
when 5 then v_out_row.idx := 5*6; v_out_row.text := 'was five';
when 6 then v_out_row.idx := 6*7; v_out_row.text := 'was SIX';
when 7 then v_out_row.idx := 7*8; v_out_row.text := 'was seven';
else v_out_row.idx :=
v_in_row.idx*10; v_out_row.text := 'was other';
end case;
pipe row ( v_out_row );
end loop;
close p_input_rows;
return;
end Mappings_Fn;
Note the syntax of the query. Its most compactly expressed using the
views v or lookups
defined above.
select value(b)
from table
(
cast
(
Mappings_Fn
(
cursor ( select * from lookups )
)
as lookups_tab
)
) b;
For completeness, heres how it looks without the view
select value(b) from table
(
cast
(
Mappings_Fn
(
cursor
( select value(a) from table
(
cast ( Lookups_Fn() as lookups_tab )
) a
)
)
as lookups_tab
)
) b;
For convenience, we can now establish the whole thing as a view
create or replace view mapped_lookups as
select value(b) rec from table
(
cast
(
Mappings_Fn
(
cursor
( select value(a) from table
(
cast ( Lookups_Fn() as lookups_tab )
) a
)
)
as lookups_tab
)
) b;
We can now access the from PL/SQL without restriction, for example
declare
cursor table_fn_cur is
select * from mapped_lookups;
rec lookup_row;
begin
open table_fn_cur;
loop
fetch table_fn_cur into rec;
exit when table_fn_cur%notfound;
Dbms_Output.Put_Line ( rec.idx || ' / ' || rec.text );
end loop;
close table_fn_cur;
end;
Note the syntax for the implicit cursor for loop
declare
begin
for j in ( select * from mapped_lookups )
loop
Dbms_Output.Put_Line ( j.rec.idx || ' / ' || j.rec.text );
end loop;
end;