to call a funktion with a rowtype Parameter - oracle

hello everyone i have the following function:
function Entfernung(v_stadt Rheinlandstädte%rowtype)
Return Abstandstabelle is
tabelle ABSTANDSTABELLE;
cursor c_städte IS
Select *
From Rheinlandstädte
;
v_andereStadt Rheinlandstädte%rowtype;
v_entfernung float;
begin
Open c_städte;
LOOP
fetch c_städte into v_andereStadt;
v_entfernung := Abstand(v_stadt, v_andereStadt);
tabelle(v_andereStadt.stadtname) := v_entfernung;
exit when c_städte%NOTFOUND;
END Loop;
close c_städte;
return tabelle;
end Entfernung;
how can i call this function in oracle. The parameter is rowtype and I cant't use SELECT function from DUAL;

A simple example:
SQL> create table tab_par(a number, b number)
2 /
Table created.
SQL> create or replace type tab_numbers as table of number
2 /
Type created.
SQL> create or replace function fun_par (r IN tab_par%rowtype) return tab_numbers is
2 retVal tab_numbers := new tab_numbers();
3 begin
4 retVal.extend(2);
5 retVal(1) := r.a;
6 retVal(2) := r.b;
7 return retVal;
8 end;
9 /
Function created.
SQL> insert into tab_par values ( 10, 5);
1 row created.
SQL> declare
2 r tab_par%rowtype;
3 n tab_numbers;
4 begin
5 select *
6 into r
7 from tab_par
8 where rownum = 1;
9 -- call your function
10 n := fun_par(r);
11 dbms_output.put_line('n = ' || n(1));
12 dbms_output.put_line('n = ' || n(2));
13 end;
14 /
n = 10
n = 5
PL/SQL procedure successfully completed.
SQL>

here is how I call this function, this function is in the package:
DECLARE
v_stadtname_a VARCHAR(20):='Düsseldorf';
v_stadtA Rheinlandstädte%rowtype;
tabelle GEOGRAPHICAL_PACKAGE.ABSTANDSTABELLE;
v_stadt Rheinlandstädte%rowtype;
CURSOR c_sta IS
SELECT * FROM Rheinlandstädte;
BEGIN
SELECT * INTO v_stadtA
FROM rheinlandstädte
WHERE stadtname=v_stadtname_a;
OPEN c_sta;
LOOP
FETCH c_sta INTO v_stadt;
EXIT WHEN c_sta%NOTFOUND;
tabelle := GEOGRAPHICAL_PACKAGE.Entfernung(v_stadtA);
dbms_output.put_line('Abstand zwischen '||v_stadtA.stadtname||' und '||
v_stadt.stadtname||' beträgt: '||tabelle(v_stadt.stadtname)||' km.');
END LOOP;
CLOSE c_sta;
END;

Related

Oracle hierarchical recursive query stop at cycle and continue with other package name

I am a little struggling at the moment with the following problem.
I want to know which package calls which packages. The table is not hierarchical.
Its the table user_dependencies.
The code so far:
CREATE OR REPLACE PACKAGE object_x is
type ObjectRec is record(
dName varchar2(250),
level number
);
type ObjectTemp is table of ObjectRec;
function Referenced(dname VARCHAR2, level NUMBER, maxl NUMBER) return ObjectTemp pipelined;
end;
/
CREATE OR REPLACE PACKAGE BODY object_x is
function Referenced(dname VARCHAR2, level NUMBER, maxl NUMBER) return ObjectTemp pipelined is
rData ObjectRec;
begin
if level >= maxl then
return;
end if;
if level = 1 then
rData.dName := name;
rData.Level := maxl;
pipe row(rData);
end if;
for r in (
select referenced_name
from user_dependencies
where name = upper(dname)
and type = 'PACKAGE BODY'
and referenced_type = 'PACKAGE'
and referenced_name != UPPER(dname)
and referenced_name != name
)
loop
rData.dName := LPAD(' ', 3, ' ') || r.Referenced_name;
rData.level := level+1;
pipe row(rData);
rData.Name := r.Referenced_name;
for r2 in (select * from table(Referenced(rData.Name, level + 1, maxl))) loop
rData.Name := LPAD(' ', 3, ' ') || r2.dName;
rData.Level := r2.Level;
pipe row(rData);
null;
end loop;
end loop;
RESULT:
Level Dname
---------- --------------------------------------------------------------------------------
1 PAC1
2 PAC2
2 PAC3
2 PAC4
2 PAC5
3 PAC6
3 PAC2
3 PAC7
3 PAC8
4 PAC9
4 PAC10
5 PAC6
5 PAC11
5 PAC3
5 PAC9
5 PAC12
5 PAC6
5 PAC3
5 PAC9
5 PAC4
5 PAC8
3 PAC10
4 PAC6
4 PAC11
4 PAC3
4 PAC9
4 PAC12
4 PAC4
EXPECTED RESULT:
Level Dname
---------- --------------------------------------------------------------------------------
1 PAC1
2 PAC2
2 PAC3
2 PAC4
2 PAC5
3 PAC6
3 PAC2
3 PAC7
3 PAC8
4 PAC9
4 PAC10
5 PAC6
5 PAC11
5 PAC3
5 PAC9
5 PAC12
5 PAC6
5 PAC3
5 PAC9
5 PAC4
5 PAC8
3 PAC10 LOOP!!!!
-----BREAK------
CONTINUE WITH OTHER PACKAGES………..
Thanks for any advice.
Ultimately, yes, it is possible to do what you want.
One way to do this is to use a nested table to store the chain of dependent packages that you've built up through the current chain of recursive function calls. You can use the MEMBER OF operator with this nested table to check whether a package is already in this chain (and so you've found a loop). If not, you can call your Referenced function recursively, but adding an extra item to this table for the current package.
I made these changes to your code and ended up with the following:
CREATE OR REPLACE TYPE varchar2_table AS TABLE OF VARCHAR2(250);
/
CREATE OR REPLACE PACKAGE object_x is
type ObjectRec is record(
dName varchar2(250),
dLevel number
);
type ObjectTemp is table of ObjectRec;
function Referenced(dname VARCHAR2, dlevel NUMBER, maxl NUMBER) return ObjectTemp pipelined;
function Referenced(dname VARCHAR2, dlevel NUMBER, maxl NUMBER, pkgs_so_far IN varchar2_table) return ObjectTemp pipelined;
end;
/
CREATE OR REPLACE PACKAGE BODY object_x is
function Referenced(dname VARCHAR2, dlevel NUMBER, maxl NUMBER) return ObjectTemp pipelined is
rData ObjectRec;
begin
for r2 in (select * from table(Referenced(dname, dlevel, maxl, varchar2_table(dname))))
loop
rData.dName := r2.dName;
rData.dLevel := r2.dLevel;
pipe row(rData);
end loop;
end;
function Referenced(dname VARCHAR2, dlevel NUMBER, maxl NUMBER, pkgs_so_far IN varchar2_table) return ObjectTemp pipelined is
rData ObjectRec;
new_pkgs_so_far varchar2_table;
loop_detected boolean;
begin
if dlevel >= maxl then
return;
end if;
if dlevel = 1 then
rData.dName := dname;
rData.dLevel := 1;
pipe row(rData);
end if;
for r in (
select referenced_name
from user_dependencies
where name = upper(dname)
and type = 'PACKAGE BODY'
and referenced_type = 'PACKAGE'
and referenced_name != UPPER(dname)
and referenced_name != name
)
loop
loop_detected := r.referenced_name MEMBER OF pkgs_so_far;
rData.dName := LPAD(' ', 3, ' ') || r.Referenced_name;
if loop_detected then
rData.dName := rData.dName || ' --- LOOP';
end if;
rData.dLevel := dLevel + 1;
pipe row(rData);
if not loop_detected THEN
new_pkgs_so_far := pkgs_so_far;
new_pkgs_so_far.EXTEND(1);
new_pkgs_so_far(new_pkgs_so_far.COUNT) := r.referenced_name;
for r2 in (select * from table(Referenced(r.referenced_name, dLevel + 1, maxl, new_pkgs_so_far))) loop
rData.dName := LPAD(' ', 3, ' ') || r2.dName;
rData.dLevel := r2.dLevel;
pipe row(rData);
end loop;
end if;
end loop;
end;
end;
/
I've modified your pipelined function to add the pkgs_so_far parameter, which contains the table of packages currently encountered. I've added another pipelined function with the same signature as your original function, and this just calls the other one with the table of packages containing only the given package.
In the modified function, we now use the MEMBER OF operator to check whether we've already come across the current package. If we have, we can add an extra --- LOOP marker to indicate this. If we haven't come across this package before, we add the package name to the table and continue to recursively examine its references. Note that assigning the table in the line new_pkgs_so_far := pkgs_so_far; appears to set new_pkgs_so_far to a copy of the table in pkgs_so_far, so we can mutate new_pkgs_so_far without this affecting pkgs_so_far.
However, there were also a number of other issues I cleared up with your code:
The package body appears to be missing the final two end; lines, one to end the procedure and one to end the package body itself.
Your code contains some references to the name field of your record, but it is named dName. I've tidied these all up to use dName.
Oracle didn't seem to like the name level being used, so I changed it to dLevel. (LEVEL is an Oracle keyword, it's used in hierarchical SQL.)
I'm not sure it's correct to pipe out a row with dLevel set to maxl in the case where the variable dlevel is 1, so I've changed this to 1 instead.
When calling your References function recursively, I've changed the first parameter to be r.referenced_name, as then we don't need to assign to rData.dName.
I've removed an unnecessary null; statement within the loop that iterates through a recursive call to your procedure.
I did also note that you've written LPAD(' ', 3, ' ') twice, but I'm not sure why: this is a long-winded way of writing ' ', where there are three spaces in the string.
Some of these errors may have arisen because you anonymised your code before posting it here but you didn't check whether the code you posted compiles before posting. In future, please ensure your code compiles, as otherwise anyone who wishes to help you will have to first fix your compilation errors.
I also don't have all of your packages (and I suspect in reality they aren't named PAC1, PAC2 and so on), so I created three packages PAC1 to PAC3. PAC2 and PAC3 both reference each other and PAC1, and the output I got was as follows:
SQL> COLUMN dname FORMAT a30
SQL> select * from table(object_x.referenced('PAC2', 1, 10));
DNAME DLEVEL
------------------------------ ----------
PAC2 1
PAC1 2
PAC3 2
PAC1 3
PAC2 --- LOOP 3

PL/SQL Table Function - How to return an empty result set?

I'm trying to create a PL/SQL table function. I don't mind if it is PIPELINED or not. I just want it to return a query-able result set.
And I want to start with an empty result set. (Because it is possible that the result set I intend to construct will be empty.)
Is it possible to create a PL/SQL table function that returns zero rows?
In the books I have, and tutorials I can find, I only see examples that must return at least one record.
Example of the problem:
CREATE OR REPLACE PACKAGE z_util AS
TYPE t_row
IS RECORD (
CATEGORY VARCHAR2( 128 CHAR )
, MEASURE NUMBER
);
TYPE t_tab
IS TABLE OF t_row;
FUNCTION f_test
RETURN t_tab;
END z_util;
/
CREATE OR REPLACE PACKAGE BODY z_util AS
FUNCTION f_test
RETURN t_tab IS
retval t_tab;
BEGIN
RETURN retval;
END;
END z_util;
/
SELECT test.*
FROM TABLE ( z_util.f_test ) test;
Output:
Error starting at line : 24 in command -
SELECT test.*
FROM TABLE ( z_util.f_test ) test
Error at Command Line : 25 Column : 14
Error report -
SQL Error: ORA-00902: invalid datatype
00902. 00000 - "invalid datatype"
*Cause:
*Action:
Something like this?
SQL> CREATE TYPE t_row AS OBJECT (id NUMBER, name VARCHAR2 (50));
2 /
Type created.
SQL> CREATE TYPE t_tab IS TABLE OF t_row;
2 /
Type created.
SQL> CREATE OR REPLACE FUNCTION f_test
2 RETURN t_tab
3 AS
4 retval t_tab;
5 BEGIN
6 RETURN retval;
7 END;
8 /
Function created.
SQL> SELECT f_test FROM DUAL;
F_TEST(ID, NAME)
--------------------------------------------------------------------
SQL>
Saying that this is too simple and that it doesn't work while in package:
SQL> CREATE OR REPLACE PACKAGE pkg_test
2 AS
3 FUNCTION f_test
4 RETURN t_tab;
5 END;
6 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY pkg_test
2 AS
3 FUNCTION f_test
4 RETURN t_tab
5 AS
6 retval t_tab;
7 BEGIN
8 RETURN retval;
9 END f_test;
10 END pkg_test;
11 /
Package body created.
SQL> select pkg_test.f_test from dual;
F_TEST(ID, NAME)
-------------------------------------------------------
SQL>
Works OK as well. Did you, by any chance, declare type within the package? If so, try to create it at SQL level.
See 6.4.6 Querying a Collection:
Note: In SQL contexts, you cannot use a function whose return type was declared in a package specification.
You cannot unnest the result of function, but the variable with the same data type:
create or replace package utils as
type t_row is record (category varchar2 (8), measure number);
type t_tab is table of t_row;
function passon (t t_tab:=null) return t_tab;
end utils;
/
create or replace package body utils as
function passon (t t_tab:=null) return t_tab is
begin
return t;
end;
end utils;
/
Usage and outcomes:
var rc refcursor
declare
tab1 utils.t_tab := utils.passon (); -- empty
tab2 utils.t_tab := utils.passon (utils.t_tab (utils.t_row ('category', 50)));
begin
open :rc for
select * from table (tab1) union all
select * from table (tab2);
end;
/
CATEGORY MEASURE
-------- ----------
category 50
jsut use a return statment without any parameters.
I have already one table function that splits a string based in token.
I modified the code for you as an example answet for your quetion.
If you pass the first string null, the function will return no rows, otherwise will return each token in separate row based on the second parameter offcurse.
// create needed types
// row object
CREATE OR REPLACE TYPE T_TOKEN_ROW AS OBJECT (
id NUMBER,
token_text VARCHAR2(50)
);
// table object
CREATE OR REPLACE TYPE T_TOKEN_TAB IS TABLE OF t_token_row;
// create table function to toknize a string
// input : P_string : the string to be toknized
// P_separator : a character to separate tokens
// Outputs : each token in separate record with id field
CREATE OR REPLACE FUNCTION PIPE_tokens (P_string varchar2,P_separator char) RETURN t_token_tab PIPELINED
AS
sLine VARCHAR2(2000);
nPos INTEGER;
nPosOld INTEGER;
nIndex INTEGER;
nLength INTEGER;
nCnt INTEGER;
sToken VARCHAR2(200);
BEGIN
if (P_string is null ) then
return ;
else
sLine := P_string;
IF (SUBSTR(sLine, LENGTH(sLine), 1) <> '|') THEN
sLine := sLine || '|';
END IF;
nPos := 0;
sToken := '';
nLength := LENGTH(sLine);
nCnt := 0;
FOR nIndex IN 1..nLength LOOP
IF ((SUBSTR(sLine, nIndex, 1) = P_separator) OR (nIndex = nLength)) THEN
nPosOld := nPos;
nPos := nIndex;
nCnt := nCnt + 1;
sToken := SUBSTR(sLine, nPosOld + 1, nPos - nPosOld - 1);
PIPE ROW(t_token_row(nCnt,sToken));
--tTokenTab(nCnt) := sToken;
END IF;
END LOOP;
RETURN;
end if;
END;
// 2 Test query
select * from table(PIPE_tokens(null,';')) ;
select * from table(PIPE_tokens('5;2;3',';')) ;

Error while creating and executing a function

I have a table as follows:
SCREENING_ID PLAN_ID THEATRE_ID SCREENING_DATE SCREENING_START_HH24 SCREENING_START_MM60
1 1 3 01.06.2015 00:00:00 9 0
2 1 3 01.06.2015 00:00:00 11 30
3 1 3 01.06.2015 00:00:00 14 0
4 1 4 01.06.2015 00:00:00 14 0
I have to check whether a particular time slot is available or not.This function should contain the following input parameters: plan_id_p, theatre_id_p, screening_date_p, screening_start_hh24_p, screening_start_mm60_p. It should return 1 if having a time slot otherwise return 0.
My code:
CREATE OR REPLACE FUNCTION Func_is_time_available
(plan_id_p IN NUMBER,
theatre_id_p IN OUT NUMBER,
screening_date_p IN OUT DATE,
screening_start_hh24_p IN OUT NUMBER,
screening_start_mm60_p IN OUT NUMBER)
RETURN NUMBER
AS
return_val NUMBER;
CURSOR cr2 IS
SELECT plan_id,
THEATRE_ID,
SCREENING_DATE,
SCREENING_START_HH24,
SCREENING_START_MM60
FROM screening s
WHERE plan_id = plan_id_p and
theatre_id=theatre_id_p and
SCREENING_DATE=SCREENING_DATE_P and
SCREENING_START_HH24=SCREENING_START_HH24_P and
SCREENING_START_MM60=SCREENING_START_MM60_P;
BEGIN
OPEN cr2;
FETCH cr2 INTO plan_id_p,
THEATRE_ID_P,
SCREENING_DATE_P,
SCREENING_START_HH24_P,
SCREENING_START_MM60_P;
IF cr2%NOTFOUND THEN
return_val := 1;
ELSE
return_val := 0;
END IF;
CLOSE cr2;
RETURN return_val;
END;
And the execution part:
DECLARE
v_result NUMBER;
BEGIN v_result:=Func_is_time_available(plan_id_p=>1,
theatre_id_p=>3,
screening_date_p=>'1/JUN/2015',
screening_start_hh24_p=>9,
screening_start_mm60_p=>0);
END;
But this is giving error as:
ORA-06550: line 18, column 44:
PLS-00363: expression '<expression>' cannot be used as an assignment target
Can anyone explain what my mistake is here?
I am using oracle.
I have made changes to your code refer below
CREATE OR REPLACE FUNCTION Func_is_time_available
(plan_id_p IN NUMBER,
theatre_id_p IN NUMBER,
screening_date_p IN DATE,
screening_start_hh24_p IN NUMBER,
screening_start_mm60_p IN NUMBER)
RETURN NUMBER
AS
return_val NUMBER;
var1 number;
begin
SELECT count(*) into var1
FROM screening s
WHERE plan_id = plan_id_p and
theatre_id=theatre_id_p and
SCREENING_DATE=SCREENING_DATE_P and
SCREENING_START_HH24=SCREENING_START_HH24_P and
SCREENING_START_MM60=SCREENING_START_MM60_P;
if var1 >= 1 then -- count can be 1 or > 1
return_val:= 1;
else return_val:=0;
end if;
end;
Make all parameters as IN instead of IN OUT and try.

Oracle stored function - pass table name as parameter

I'm trying to create a stored function in Oracle that will count the table rows..i want to make the table name dynamic, so i passed it as a parameter, the stored function code looks like this
create type tes_jml_obj is object(jumlah integer);
create type tes_jml_table is table of tes_jml_obj;
create or replace function jumlahBaris(namatabel varchar)
return tes_jml_table
is
tabel tes_jml_table := tes_jml_table();
begin
for r in (execute immediate 'select count(*) as jumlah from' || namatabel)
loop
tabel.extend;
tabel(1) := tes_jml_obj(r.jumlah);
end loop;
return tabel;
end;
But when i execute it, it returns errors. Am i missing something here? Is that the correct way to get the table rows dynamically?
There is a space missing after FROM keyword in the EXECUTE IMMEDIATE statement.
EXECUTE IMMEDIATE statement has a syntax error. You are missing the INTO clause.
You cannot use EXECUTE IMMEDIATE inside a CURSOR FOR LOOP. Basically, you are returning nothing from the execute immediate statement as mentioned in point 2 above.
The iteration syntax for the LOOP is not correct. The syntax is FOR r IN 1..COUNT().
After rectifying your code, this is how it would look like:
SQL> CREATE OR REPLACE TYPE TES_JML_OBJ IS OBJECT(JUMLAH NUMBER)
2 /
Type created.
SQL> CREATE OR REPLACE TYPE TES_JML_TABLE IS TABLE OF TES_JML_OBJ
2 /
Type created.
SQL> CREATE OR REPLACE
2 FUNCTION jumlahBaris(
3 namatabel VARCHAR2)
4 RETURN tes_jml_table
5 IS
6 TABEL TES_JML_TABLE := TES_JML_TABLE();
7 cnt NUMBER;
8 BEGIN
9 EXECUTE IMMEDIATE 'select count(*) as jumlah from ' || NAMATABEL INTO CNT;
10 FOR R IN 1..CNT
11 LOOP
12 TABEL.EXTEND;
13 TABEL(R) := TES_JML_OBJ(R);
14 dbms_output.put_line(TES_JML_OBJ(R).jumlah);
15 END LOOP;
16 RETURN tabel;
17 END;
18 /
Function created.
SQL> SHO ERR
No errors.
So, the function compiled with no errors. Let's execute it and see the output:
SQL> SET SERVEROUTPUT ON
SQL> SELECT JUMLAHBARIS('EMP') FROM DUAL;
JUMLAHBARIS('EMP')(JUMLAH)
--------------------------------------------------------------------------------
TES_JML_TABLE(TES_JML_OBJ(1), TES_JML_OBJ(2), TES_JML_OBJ(3), TES_JML_OBJ(4), TE
S_JML_OBJ(5), TES_JML_OBJ(6), TES_JML_OBJ(7), TES_JML_OBJ(8), TES_JML_OBJ(9), TE
S_JML_OBJ(10), TES_JML_OBJ(11), TES_JML_OBJ(12), TES_JML_OBJ(13), TES_JML_OBJ(14
))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL>
Your execute immediate will return only one value, the count, so what is there to loop over?
Also I'm not sure that execute immediate works with an implicit cursor.
In your SQL it looks like you don't have a space after the from keyword.
Try something like this instead:
create or replace function jumlahBaris(namatabel varchar)
return tes_jml_table
is
tabel tes_jml_table := tes_jml_table();
the_count integer;
the_sql varchar(100);
begin
the_sql := 'select count(*) as jumlah from ' || namatabel;
execute immediate the_sql INTO the_count;
if the_count IS NOT NULL THEN
tabel.extend;
tabel(1) := tes_jml_obj(the_count);
end if;
return tabel;
end;

Return collection from packaged function for use in select

I'm currently using this block of code to return a collection of rows from my function.
--Source: http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html
create or replace type t_col as object (
i number,
n varchar2(30)
);
/
create or replace type t_nested_table as table of t_col;
/
create or replace function return_table return t_nested_table as
v_ret t_nested_table;
begin
v_ret := t_nested_table();
v_ret.extend;
v_ret(v_ret.count) := t_col(1, 'one');
v_ret.extend;
v_ret(v_ret.count) := t_col(2, 'two');
v_ret.extend;
v_ret(v_ret.count) := t_col(3, 'three');
return v_ret;
end return_table;
/
Which I call by issuing SQL
select * from table(return_table);
Object types can not be defined in a package, I tried using the record type which worked (in PL/SQL) but I couldn't select from it in the same way as I can here.
How do I achieve this result using a function inside a package?
You could either use SQL objects inside your package or use pipelined functions (tested with 10gr2). Using SQL objects is straightforward, your actual function could be used as is inside a package.
Here's how you could use a pipelined function with a RECORD type:
SQL> CREATE OR REPLACE PACKAGE my_pkg IS
2 TYPE t_col IS RECORD(
3 i NUMBER,
4 n VARCHAR2(30));
5 TYPE t_nested_table IS TABLE OF t_col;
6 FUNCTION return_table RETURN t_nested_table PIPELINED;
7 END my_pkg;
8 /
Package created
SQL> CREATE OR REPLACE PACKAGE BODY my_pkg IS
2 FUNCTION return_table RETURN t_nested_table PIPELINED IS
3 l_row t_col;
4 BEGIN
5 l_row.i := 1;
6 l_row.n := 'one';
7 PIPE ROW(l_row);
8 l_row.i := 2;
9 l_row.n := 'two';
10 PIPE ROW(l_row);
11 RETURN;
12 END;
13 END my_pkg;
14 /
Package body created
SQL> select * from table(my_pkg.return_table);
I N
---------- ------------------------------
1 one
2 two
What happens behind the scene is that Oracle understands that since you want to use your function in a query (because of the PIPELINED keyword), you will need SQL objects, so those objects are created behind the scene for you:
SQL> select object_name
2 from user_objects o
3 where o.created > sysdate - 1
4 and object_type = 'TYPE';
OBJECT_NAME
--------------------------------------------------------------------------------
SYS_PLSQL_798806_24_1
SYS_PLSQL_798806_DUMMY_1
SYS_PLSQL_798806_9_1
SQL> select text from user_source where name='SYS_PLSQL_798806_9_1';
TEXT
--------------------------------------------------------------------------------
type SYS_PLSQL_798806_9_1 as object (I NUMBER,
N VARCHAR2(30));
create or replace type t_col as object (
i number,
n varchar2(30)
);
/
create or replace package foo as
type t_nested_table is table of t_col;
function return_table return t_nested_table pipelined;
end;
/
show errors
create or replace package body foo as
data t_nested_table := t_nested_table(t_col(1, 'one'),
t_col(2, 'two'),
t_col(3, 'three'));
function return_table return t_nested_table pipelined as
begin
for i in data.first .. data.last loop
pipe row(data(i));
end loop;
return;
end;
end;
/
show errors
column n format a10
select * from table(foo.return_table);
I N
---------- ----------
1 one
2 two
3 three

Resources