简体   繁体   中英

PL/SQL Passing a local collection into a pipelined function

I need to pass a locally defined table type to a function which is a pipelined function returning another locally defined table type.

Here is sample data:

create table my_tab
(i NUMBER,
 n VARCHAR2(30));

 insert into my_tab values (1, 'Peter');
 insert into my_tab values (2, 'Dakshesh');
 insert into my_tab values (1, 'Maggie');
 insert into my_tab values (3, 'Madhu');
 commit;

My code is:

CREATE OR REPLACE PACKAGE my_pkg IS
    TYPE t_col IS RECORD(
    i NUMBER,
    n VARCHAR2(30));
    TYPE t_nested_table IS TABLE OF t_col;
    TYPE t_number IS TABLE OF NUMBER;
    FUNCTION iterate_table RETURN t_number PIPELINED;
    FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
     g_number t_number ;
     g_nested_number t_nested_table ;
  END my_pkg;
  /

Body:

 CREATE OR REPLACE PACKAGE BODY my_pkg IS
    FUNCTION iterate_table RETURN t_number PIPELINED IS
    BEGIN
      IF ( (g_number IS NOT NULL) AND (g_number.EXISTS (1)))
      THEN
         FOR i IN 1 .. g_number.COUNT
         LOOP
            IF g_number (i) IS NOT NULL
            THEN
               PIPE ROW (g_number (i));
            END IF;
         END LOOP;
      END IF;
      RETURN;
   EXCEPTION
      WHEN OTHERS
      THEN
         RAISE;
   END iterate_table;

   FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED IS
      l_row t_nested_table ;
      CURSOR cur_test IS
          select mt.i, mt.n 
          from my_tab mt, TABLE(iterate_table ) tab
          where mt.i = tab.column_value;
     BEGIN
         OPEN cur_test;
         FETCH cur_test BULK COLLECT into l_row;
         CLOSE cur_test;
         FOR i IN 1..l_row.COUNT
         LOOP
             PIPE ROW(l_row(i));
         END LOOP;
         RETURN;
     END return_table;
 END my_pkg;
 /

Now this code compiles successfully, when I try to invoke it like a pipelined function, it gives error-

select * from table(my_pkg.return_table(my_pkg.t_number(1)));

Error- ORA-00902: invalid datatype 00902. 00000 - "invalid datatype" *Cause:
*Action: Error at Line: 14 Column: 41
ORA-00902: invalid datatype 00902. 00000 - "invalid datatype" *Cause:
*Action: Error at Line: 14 Column: 41

The two pre-requisites for this code are -

  1. the collections should be all locally defined.

  2. the function should be pipelined.

Help!!

I am not getting any error with table and its a single table so no foreign key constraints hold.

It is not possible in oracle 11. I don't know why oracle throws "invalid data type". If you put this query into anonymous block you will receive PLS-00642: Local Collection Types Not Allowed in SQL Statement

If you don't want or you cannot create sql level collection. The solution is use predefined type. Good source of predefined collection is Oracle Data Cartridge . Replace all t_number with ODCINumberList .

predefined collections

In Oracle 10 and 11, it is not possible to use collections in the SQL scope that have been defined in a PL/SQL scope. In Oracle 12 , what you are trying should work.

If you want to do this then declare your types in the SQL scope (not in the package).

CREATE OR REPLACE TYPE t_col IS OBJECT(
  i NUMBER,
  n VARCHAR2(30)
);
/

CREATE OR REPLACE TYPE t_nested_table IS TABLE OF t_col;
/

CREATE OR REPLACE TYPE t_number IS TABLE OF NUMBER;
/

CREATE OR REPLACE PACKAGE my_pkg IS
  FUNCTION iterate_table RETURN t_number PIPELINED;
  FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
  g_number t_number ;
  g_nested_number t_nested_table ;
END my_pkg;
/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM