Create the PTF implementation package stack_p.
CREATE PACKAGE stack_p AS 
 
  FUNCTION  describe(tab  IN OUT dbms_tf.table_t,  
                     col         dbms_tf.columns_t) 
            RETURN dbms_tf.describe_t; 
 
  PROCEDURE fetch_rows; 
 
END stack_p;  
                        Package created.
Create the PTF implementation package body stack_p.
CREATE PACKAGE BODY stack_p AS 
 
  FUNCTION  describe(tab  IN OUT dbms_tf.table_t,  
                     col         dbms_tf.columns_t) 
            RETURN dbms_tf.describe_t  AS 
  BEGIN 
    FOR i IN 1 .. tab.column.count LOOP 
      FOR j IN 1 .. col.count LOOP 
        IF (tab.column(i).description.name = col(j) AND 
            tab.column(i).description.TYPE = dbms_tf.type_number) THEN 
          tab.column(i).pass_through := false; 
          tab.column(i).for_read     := true; 
        END IF; 
      END LOOP; 
    END LOOP; 
 
    RETURN dbms_tf.describe_t( 
             new_columns => dbms_tf.columns_new_t( 
               1 => dbms_tf.column_metadata_t(name => 'COLUMN_NAME',  
                                              TYPE => dbms_tf.type_varchar2), 
               2 => dbms_tf.column_metadata_t(name => 'COLUMN_VALUE', 
                                              TYPE => dbms_tf.type_number)), 
             row_replication => true); 
  END; 
 
  PROCEDURE fetch_rows  AS 
    env    dbms_tf.env_t := dbms_tf.get_env(); 
    rowset dbms_tf.row_set_t; 
    colcnt PLS_INTEGER; 
    rowcnt PLS_INTEGER; 
    repfac dbms_tf.tab_naturaln_t; 
    namcol dbms_tf.tab_varchar2_t; 
    valcol dbms_tf.tab_number_t;  
  BEGIN  
    dbms_tf.get_row_set(rowset, rowcnt, colcnt); 
 
    FOR i IN 1 .. rowcnt LOOP repfac(i) := 0; END LOOP; 
 
    FOR r IN 1 .. rowcnt LOOP 
      FOR c IN 1 .. colcnt LOOP 
        IF rowset(c).tab_number(r) IS NOT NULL THEN 
          repfac(r)                    := repfac(r) + 1; 
          namcol(nvl(namcol.last+1,1)) :=  
            initcap(regexp_replace(env.get_columns(c).name, '^"|"$')); 
          valcol(nvl(valcol.last+1,1)) := rowset(c).tab_number(r); 
        END IF; 
      END LOOP; 
    END LOOP; 
 
    dbms_tf.row_replication(replication_factor => repfac); 
    dbms_tf.put_col(1, namcol); 
    dbms_tf.put_col(2, valcol); 
 
  END; 
 
END stack_p;  
                        Package Body created.
Create the standalone PTF named stack.
CREATE FUNCTION stack(tab TABLE,  
                      col COLUMNS) 
      RETURN TABLE PIPELINED ROW POLYMORPHIC USING stack_p; 
                        Function created.
Invoke the PTF stack in a query.
SELECT   deptno, ename, column_name, column_value 
FROM     stack(scott.emp, COLUMNS(mgr, sal, comm))  
WHERE    deptno IN (10, 30) 
ORDER BY deptno, ename
                        | DEPTNO | ENAME | COLUMN_NAME | COLUMN_VALUE | 10 | CLARK | Mgr | 7839 | 10 | CLARK | Sal | 2450 | 10 | KING | Sal | 5000 | 10 | MILLER | Mgr | 7782 | 10 | MILLER | Sal | 1300 | 30 | ALLEN | Mgr | 7698 | 30 | ALLEN | Comm | 300 | 30 | ALLEN | Sal | 1600 | 30 | BLAKE | Mgr | 7839 | 30 | BLAKE | Sal | 2850 | 30 | JAMES | Mgr | 7698 | 30 | JAMES | Sal | 950 | 30 | MARTIN | Mgr | 7698 | 30 | MARTIN | Comm | 1400 | 30 | MARTIN | Sal | 1250 | 30 | TURNER | Mgr | 7698 | 30 | TURNER | Comm | 0 | 30 | TURNER | Sal | 1500 | 30 | WARD | Mgr | 7698 | 30 | WARD | Sal | 1250 | 30 | WARD | Comm | 500 | 
|---|