Skip to Main Content
  • Questions
  • Open ref cursor for sql stored in a clob variable

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Bhanu.

Asked: October 15, 2007 - 3:33 pm UTC

Last updated: March 19, 2009 - 10:46 am UTC

Version: 10.0.1

Viewed 10K+ times! This question is

You Asked

i have a sql query of length 375019. I used a clob variable to store the query as i cannot use the varchar2 type variable. When i try to execute the statement " open ref_cur for v_clob", it throws an error . Is this something doable? Kindly help!


SQL>create table clob_test( id int, text clob);


DECLARE
l_clob CLOB;
l_text varchar2 (50) := ' UNION SELECT * from dual';
BEGIN
DBMS_LOB.createtemporary (l_clob, TRUE);
DBMS_LOB.OPEN (l_clob, DBMS_LOB.lob_readwrite);
dbms_lob.write (l_clob, length('SELECT * from dual'), 1, 'SELECT * from dual');

FOR i IN 1 .. 15000
LOOP
DBMS_LOB.writeappend (l_clob,length(l_text), l_text);
END LOOP;

INSERT INTO clob_test
(ID, text
)
VALUES (0, l_clob||';'
);
commit;

DBMS_LOB.CLOSE (l_clob);
DBMS_LOB.freetemporary (l_clob);
END;


SQL> declare
2 v_sql clob;
3 o_cur sys_refcursor;
4 Begin
5 select text into v_sql from clob_test;
6 open o_cur for v_sql;
7 End;
8 /
open o_cur for v_sql;
*
ERROR at line 6:
ORA-06550: line 6, column 18:
PLS-00382: expression is of wrong type
ORA-06550: line 6, column 3:
PL/SQL: Statement ignored

and Tom said...

Not until 11g - this is a new feature in 11g, support for native dynamic sql using LOBS.

http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/whatsnew.htm#CHDGIGFJ

prior to that, you may use DBMS_SQL to parse a query stored in an array - and that can exceed 32k in total length.

http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm#sthref7554

see the overloaded parse routine - the second two variants accept a sqlstatement in an array.

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:6161200355268


Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Still unsure how to return ref cursor using dbms_sql

A reader, November 12, 2008 - 1:17 am UTC

had a look at the oracle documentation, i know how to use dbms_sql and parse cursors etc, but how does one use dbms_sql to open a ref cursor and return it to the calling program ?

whats the equivalent of

OPEN some_ref_cursor for some_variable_with_sql ;

cheers

Tom Kyte
November 12, 2008 - 10:33 am UTC

what version

Opening a cursor in oracle 10g - still not clear

Parag Gujarathi, February 13, 2009 - 9:48 am UTC

We are using a clob to store a very large query > 32K. We are not able to open a cursor to be returned to the calling program

open cursor cur for v_clob;

In 11g this is a new feature, but how do we do it in 10g? The dbms_parse package will parse and execute the query, but we need to send out a ref cursor to the calling program, is this possible?

Tom Kyte
February 16, 2009 - 11:16 am UTC

It is not possible in 10g

In 10g, best you can do is a dbms_sql cursor, you could write a pipelined function to return it as a ref cursor, but you would have to know AT COMPILE TIME how many columns there were, and their datatypes and their names. (since you have to create an object type to match the output specification of the pipelined function)

Open clob in a ref cursor

A reader, March 19, 2009 - 4:29 am UTC

Thanks for the reply. The approach you suggested was a good one (something new I came to know of :-)) but sadly it was not feasible in our case as the number of columns were variable.

We overcame this in a sort of crude way. We created the query like v_clob := 'INSERT INTO <table> ' || v_clob;

So now we are inserting data in a table and opening ref cursor as select * from <table>. Crude way and understnad that performance my be impacted a bit, but it works for now. Will have to rewrite when we move to 11g :-).

Thanks for your help.
Tom Kyte
March 19, 2009 - 10:46 am UTC

if you are using execute immediate to execute that >32k statement, it is only working by accident (if it is working) and you should rethink your approach.

you could

a) create the clob for the insert
b) break it into an array
c) use dbms_sql to parse the array of any size

but do not use execute immediate on it, your application can break at any time

More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here