Home » SQL & PL/SQL » SQL & PL/SQL » Create table by using REF Cursor Results (Oracle 11i )
Create table by using REF Cursor Results [message #525727] Tue, 04 October 2011 22:34 Go to next message
saipradyumn
Messages: 419
Registered: October 2011
Location: Hyderabad
Senior Member

Hi All ,

I want to create table by using the ref cursor results which is returned by the function / procedure.
We need achieve this simple query .

Thanks in advance
Sai Pradyumn
Re: Create table by using REF Cursor Results [message #525728 is a reply to message #525727] Tue, 04 October 2011 22:42 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
It would be helpful if you followed Posting Guidelines - http://www.orafaq.com/forum/t/88153/0/

>I want to create table by using the ref cursor results which is returned by the function / procedure.
>We need achieve this simple query .

Doing DDL from inside PL/SQL is generally a bad idea.

So what business problem are you actually trying to solve?

What happens the second time this code is run?
Re: Create table by using REF Cursor Results [message #525732 is a reply to message #525728] Tue, 04 October 2011 23:55 Go to previous messageGo to next message
saipradyumn
Messages: 419
Registered: October 2011
Location: Hyderabad
Senior Member
Hi

Sorry for the in inconvenience

For example I have function like

CREATE OR REPLACE FUNCTION GETEMPLIST(DNO IN NUMBER)
RETURN SYS_REFCURSOR
IS
RETURN_VALUE SYS_REFCURSOR;
BEGIN
OPEN RETURN_VALUE FOR
SELECT* FROM SCOTT.EMP S
WHERE S.DEPTNO = DNO;
RETURN RETURN_VALUE;
END;

To Execute the function i have defined one REF Cursor variable

BEGIN
-- CALL THE FUNCTION
:RESULT := GETEMPLIST(DNO => 10);
END;

Now i want to create a table with ref cursor variable ("RESULT" ) information .

This can be done my executing the following query .

CREATE TABLE TEST_EMP AS SELECT * FROM EMP
WHERE DEPTNO = 10 ;

But in my function i have some calculations which are not possible by using simple query.

Thanks in Advance
Sai pradyumn

[Updated on: Wed, 05 October 2011 01:26] by Moderator

Report message to a moderator

Re: Create table by using REF Cursor Results [message #525733 is a reply to message #525732] Wed, 05 October 2011 00:07 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
>But in my function i have some calculations which are not possible by using simple query.

CREATE TABLE can only exist as plain SQL.

Either plain SQL will suffice, or it can not be done.
Re: Create table by using REF Cursor Results [message #525743 is a reply to message #525732] Wed, 05 October 2011 01:28 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
You want to create a table using something like:
"create table ... as <ref cursor>"?
This is not possible.

As BlackSwan said: "So what business problem are you actually trying to solve?", maybe we can find a solution for it.

Regards
Michel
Re: Create table by using REF Cursor Results [message #525822 is a reply to message #525743] Wed, 05 October 2011 14:35 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
I suspect that if you provide your business requirement there will be a simpler way to accomplish what you want. However, I have provided a demonstration below that I believe does what you asked for, assuming that this might be a simplification of a greater problem. I gather that you have a function that returns the rows that you want and you want to be able to use the ref cursor value returned from that function in a create table statement to create a table with that data as you would with a standard create table ... as select ... (ctas). I have created a packaged pipelined table function that converts the ref cursor to pipelined rows that you can use in this manner. The demonstration assumes that you have the standard scott.emp demo table.

-- the function you provided:
SCOTT@orcl_11gR2> CREATE OR REPLACE FUNCTION GETEMPLIST
  2    (DNO IN NUMBER)
  3    RETURN SYS_REFCURSOR
  4  IS
  5    RETURN_VALUE SYS_REFCURSOR;
  6  BEGIN
  7    OPEN RETURN_VALUE FOR
  8    SELECT * FROM SCOTT.EMP S
  9    WHERE  S.DEPTNO = DNO;
 10    RETURN RETURN_VALUE;
 11  END;
 12  /

Function created.


-- packaged pipelined table function:
SCOTT@orcl_11gR2> CREATE OR REPLACE PACKAGE refcur_to_table_pkg
  2  AS
  3    TYPE refcur_t IS REF CURSOR RETURN emp%ROWTYPE;
  4    TYPE outrec_typ IS RECORD
  5  	 (EMPNO     NUMBER(4),
  6  	  ENAME     VARCHAR2(10),
  7  	  JOB	    VARCHAR2(9),
  8  	  MGR	    NUMBER(4),
  9  	  HIREDATE  DATE,
 10  	  SAL	    NUMBER(7,2),
 11  	  COMM	    NUMBER(7,2),
 12  	  DEPTNO    NUMBER(2));
 13    TYPE outrecset IS TABLE OF outrec_typ;
 14    FUNCTION refcur_to_table_func
 15  	 (p	 refcur_t)
 16  	  RETURN outrecset PIPELINED;
 17  END refcur_to_table_pkg;
 18  /

Package created.

SCOTT@orcl_11gR2> SHOW ERRORS
No errors.
SCOTT@orcl_11gR2> CREATE OR REPLACE PACKAGE BODY refcur_to_table_pkg
  2  AS
  3    FUNCTION refcur_to_table_func
  4  	 (p	 refcur_t)
  5  	  RETURN outrecset PIPELINED
  6    IS
  7  	 out_rec  outrec_typ;
  8    BEGIN
  9  	 LOOP
 10  	   FETCH p INTO out_rec;
 11  	   EXIT WHEN p%NOTFOUND;
 12  	   PIPE ROW (out_rec);
 13  	 END LOOP;
 14  	 CLOSE p;
 15  	 RETURN;
 16    END refcur_to_table_func;
 17  END refcur_to_table_pkg;
 18  /

Package body created.

SCOTT@orcl_11gR2> SHOW ERRORS
No errors.


-- usage of above functions to create table:
SCOTT@orcl_11gR2> CREATE TABLE test_emp
  2  AS
  3  SELECT *
  4  FROM   TABLE
  5  	      (refcur_to_table_pkg.refcur_to_table_func
  6  		(getemplist (10)))
  7  /

Table created.


-- results:
SCOTT@orcl_11gR2> DESC test_emp
 Name                                                  Null?    Type
 ----------------------------------------------------- -------- ------------------------------------
 EMPNO                                                          NUMBER(4)
 ENAME                                                          VARCHAR2(10)
 JOB                                                            VARCHAR2(9)
 MGR                                                            NUMBER(4)
 HIREDATE                                                       DATE
 SAL                                                            NUMBER(7,2)
 COMM                                                           NUMBER(7,2)
 DEPTNO                                                         NUMBER(2)

SCOTT@orcl_11gR2> SELECT * FROM test_emp
  2  /

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
      7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10
      7839 KING       PRESIDENT            17-NOV-81       5000                    10
      7934 MILLER     CLERK           7782 23-JAN-82       1300                    10

3 rows selected.

SCOTT@orcl_11gR2>









Re: Create table by using REF Cursor Results [message #525826 is a reply to message #525822] Thu, 06 October 2011 00:19 Go to previous messageGo to next message
oralover2006
Messages: 144
Registered: January 2010
Location: India
Senior Member
Great demonstration Barbara
much appreciable efforts to teach us.
you people are doing as much as you can, very sincerely, to educate us.

with Regards.

[Updated on: Thu, 06 October 2011 00:21]

Report message to a moderator

Re: Create table by using REF Cursor Results [message #525828 is a reply to message #525826] Thu, 06 October 2011 00:58 Go to previous messageGo to next message
_jum
Messages: 577
Registered: February 2008
Senior Member
Thanks a lot! Would only suggest to define outrecset consistent as TABLE of emp%rowtype:
       TYPE refcur_t IS REF CURSOR RETURN emp%ROWTYPE;
       TYPE outrecset IS TABLE OF emp%ROWTYPE;
--     TYPE outrec_typ IS RECORD
--   	 (EMPNO     NUMBER(4),
--   	  ENAME     VARCHAR2(10),
--   	  JOB	    VARCHAR2(9),
--   	  MGR	    NUMBER(4),
--   	  HIREDATE  DATE,
--   	  SAL	    NUMBER(7,2),
--   	  COMM	    NUMBER(7,2),
--   	  DEPTNO    NUMBER(2));
--     TYPE outrecset IS TABLE OF outrec_typ;
 
Re: Create table by using REF Cursor Results [message #525853 is a reply to message #525828] Thu, 06 October 2011 04:58 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
_jum wrote on Wed, 05 October 2011 22:58
Thanks a lot! Would only suggest to define outrecset consistent as TABLE of emp%rowtype:
       TYPE refcur_t IS REF CURSOR RETURN emp%ROWTYPE;
       TYPE outrecset IS TABLE OF emp%ROWTYPE;
--     TYPE outrec_typ IS RECORD
--   	 (EMPNO     NUMBER(4),
--   	  ENAME     VARCHAR2(10),
--   	  JOB	    VARCHAR2(9),
--   	  MGR	    NUMBER(4),
--   	  HIREDATE  DATE,
--   	  SAL	    NUMBER(7,2),
--   	  COMM	    NUMBER(7,2),
--   	  DEPTNO    NUMBER(2));
--     TYPE outrecset IS TABLE OF outrec_typ;
 


I don't think so. Not with a pipelined table function. What would you use instead of ourec_typ? What would you fetch into and pipe out? Please provide a demo using what you suggest that compiles and runs, as I did.



Re: Create table by using REF Cursor Results [message #525855 is a reply to message #525853] Thu, 06 October 2011 05:25 Go to previous messageGo to next message
_jum
Messages: 577
Registered: February 2008
Senior Member
Here is the complete demo code:
CREATE OR REPLACE FUNCTION GETEMPLIST (DNO IN NUMBER)
    RETURN SYS_REFCURSOR
  IS
    RETURN_VALUE SYS_REFCURSOR;
  BEGIN
    OPEN RETURN_VALUE FOR
      SELECT * FROM SCOTT.EMP S
       WHERE  S.DEPTNO = DNO;
    RETURN RETURN_VALUE;
  END;
/

CREATE OR REPLACE PACKAGE refcur_to_table_pkg
  AS 
    TYPE refcur_t  IS REF CURSOR RETURN emp%ROWTYPE;
    TYPE outrecset IS TABLE OF          emp%ROWTYPE;
    out_rec                             emp%ROWTYPE;
    FUNCTION refcur_to_table_func (p refcur_t)
      RETURN outrecset PIPELINED;
  END refcur_to_table_pkg;
   /
   
CREATE OR REPLACE PACKAGE BODY refcur_to_table_pkg
  AS
    FUNCTION refcur_to_table_func (p     refcur_t)
      RETURN outrecset PIPELINED
  IS
    BEGIN
      LOOP
        FETCH p INTO out_rec;
        EXIT WHEN p%NOTFOUND;
        PIPE ROW (out_rec);
      END LOOP;
      CLOSE p;
      RETURN;
    END refcur_to_table_func;
  END refcur_to_table_pkg;
/

SHOW ERRORS

SELECT *
   FROM TABLE(refcur_to_table_pkg.refcur_to_table_func (getemplist (10)));

     EMPNO ENAME      JOB              MGR        SAL     DEPTNO
---------- ---------- --------- ---------- ---------- ----------
      7782 CLARK      MANAGER         7839       2450         10
      7839 KING       PRESIDENT                  5000         10
      7934 MILLER     CLERK           7782       1300         10

[Updated on: Thu, 06 October 2011 05:27]

Report message to a moderator

Re: Create table by using REF Cursor Results [message #525872 is a reply to message #525855] Thu, 06 October 2011 07:02 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
Ah, I see. The missing piece was:

out_rec emp%ROWTYPE;

In your first post, I just saw that you had commented out outrec_typ and had not provided a substitute. If you know that you will be returning the same data structure as the whole table, then this is certainly simpler. If you only want to select some columns or even columns from a join of multiple tables, then I would use the record.



Re: Create table by using REF Cursor Results [message #525905 is a reply to message #525872] Thu, 06 October 2011 14:10 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Barbara,

Both your _jum's solutions imply refcursor result rowtype is known upfront. In such case XML could be a simpler solution - no need for pipelined function. For example, if refcursor returns emp%rowtype:

select  extractvalue(column_value,'ROW/EMPNO') empno ,
        extractvalue(column_value,'ROW/ENAME') ename,
        extractvalue(column_value,'ROW/JOB') job,
        extractvalue(column_value,'ROW/MGR') mgr,
        extractvalue(column_value,'ROW/HIREDATE') hiredate,
        extractvalue(column_value,'ROW/SAL') sal,
        extractvalue(column_value,'ROW/COMM') comm,
        extractvalue(column_value,'ROW/DEPTNO') deptno
  from  table(xmlsequence(getemplist(10)))
/

EMPNO ENAME      JOB        MGR   HIREDATE   SAL        COMM       DEPTN
----- ---------- ---------- ----- ---------- ---------- ---------- -----
7782  CLARK      MANAGER    7839  09-JUN-81  2450                  10
7839  KING       PRESIDENT        17-NOV-81  5000                  10
7934  MILLER     CLERK      7782  23-JAN-82  1300                  10

SQL> 


SY.
Re: Create table by using REF Cursor Results [message #525906 is a reply to message #525905] Thu, 06 October 2011 14:37 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Actually, this might be better:

ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'
/
select  *
  from xmltable(
                '/ROWSET/*'
                passing xmltype(getemplist(10))
                columns
                  empno number(4) path '/ROW/EMPNO',
                  ename varchar2(10) path '/ROW/ENAME',
                  job varchar2(9) path '/ROW/JOB',
                  mgr number(4) path '/ROW/MGR',
                  hiredate date path '/ROW/HIREDATE',
                  sal number(7,2) path '/ROW/SAL',
                  comm number(7,2) path '/ROW/COMM',
                  deptno number(2) path '/ROW/DEPTNO'
)
/

     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
      7782 CLARK      MANAGER         7839 1981-06-09       2450                    10
      7839 KING       PRESIDENT            1981-11-17       5000                    10
      7934 MILLER     CLERK           7782 1982-01-23       1300                    10

SQL> 


SY.
Re: Create table by using REF Cursor Results [message #525917 is a reply to message #525906] Thu, 06 October 2011 18:07 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
Solomon,

Both of your suggestions are certainly a lot less code and probably quite efficient. I like the second one better, because you can specify the data types, instead of ending up with every column as varchar2(4000). However, I find it odd that it only works with certain nls_date_format's. You would think that since the function returns it in the default session format that the xmltable would expect it in the same default format. I wonder why it doesn't or if there is another way to work around that without altering the nls_date_format for the session.

Re: Create table by using REF Cursor Results [message #525952 is a reply to message #525906] Fri, 07 October 2011 01:58 Go to previous messageGo to next message
_jum
Messages: 577
Registered: February 2008
Senior Member
Interesting solution - thanks for sharing it!
Re: Create table by using REF Cursor Results [message #525988 is a reply to message #525952] Fri, 07 October 2011 05:55 Go to previous messageGo to next message
saipradyumn
Messages: 419
Registered: October 2011
Location: Hyderabad
Senior Member
Hi All ,
Thanks all of u
Really all these are fantastic solutions
Thank you very much once again
Sai pradyumn
Re: Create table by using REF Cursor Results [message #525998 is a reply to message #525917] Fri, 07 October 2011 07:58 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Barbara Boehmer wrote on Thu, 06 October 2011 19:07
However, I find it odd that it only works with certain nls_date_format's. You would think that since the function returns it in the default session format that the xmltable would expect it in the same default format. I wonder why it doesn't or if there is another way to work around that without altering the nls_date_format for the session.



10.2 Docs
Formatting of XML Dates and Timestamps
The XML Schema standard specifies that dates and timestamps in XML data be in standard formats. XML generation functions in Oracle XML DB produce XML dates and timestamps according to this standard.

In releases prior to Oracle Database 10g Release 2, the database settings for date and timestamp formats were used for XML, instead of the XML Schema standard formats. You can reproduce this previous behavior by setting the database event 19119, level 0x8, as follows:

ALTER SESSION SET EVENTS '19119 TRACE NAME CONTEXT FOREVER, LEVEL 0x8';


Therefore, without altering NLS_DATE_FORMAT you need something like:

SQL> select  *
  2    from xmltable(
  3                  '/ROWSET/*'
  4                  passing xmltype(getemplist(10))
  5                  columns
  6                    empno number(4) path '/ROW/EMPNO',
  7                    ename varchar2(10) path '/ROW/ENAME',
  8                    job varchar2(9) path '/ROW/JOB',
  9                    mgr number(4) path '/ROW/MGR',
 10                    hiredate date path '/ROW/HIREDATE',
 11                    sal number(7,2) path '/ROW/SAL',
 12                    comm number(7,2) path '/ROW/COMM',
 13                    deptno number(2) path '/ROW/DEPTNO'
 14  )
 15  /
select  *
*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected


SQL> 
SQL> select  empno,
  2          ename,
  3          job,
  4          mgr,
  5          to_date(hiredate) hiredate,
  6          sal,
  7          comm,
  8          deptno
  9    from xmltable(
 10                  '/ROWSET/*'
 11                  passing xmltype(getemplist(10))
 12                  columns
 13                    empno number(4) path '/ROW/EMPNO',
 14                    ename varchar2(10) path '/ROW/ENAME',
 15                    job varchar2(9) path '/ROW/JOB',
 16                    mgr number(4) path '/ROW/MGR',
 17                    hiredate varchar2(50) path '/ROW/HIREDATE',
 18                    sal number(7,2) path '/ROW/SAL',
 19                    comm number(7,2) path '/ROW/COMM',
 20                    deptno number(2) path '/ROW/DEPTNO'
 21  )
 22  /

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
      7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10
      7839 KING       PRESIDENT            17-NOV-81       5000                    10
      7934 MILLER     CLERK           7782 23-JAN-82       1300                    10

SQL> 


SY.
Re: Create table by using REF Cursor Results [message #526033 is a reply to message #525998] Fri, 07 October 2011 13:18 Go to previous message
Barbara Boehmer
Messages: 9090
Registered: November 2002
Location: California, USA
Senior Member
Solomon,

Thanks very much for the thorough explanation and workaround with demonstration. That clarifies it completely.
Previous Topic: Sql Query Required
Next Topic: Need help
Goto Forum:
  


Current Time: Tue Apr 23 05:17:09 CDT 2024