您的位置:首页 > 其它

Returning clob to varchar from a stored procedure

2004-10-22 21:57 597 查看
February 20, 2004 Jesse -- Thanks for the question regarding "Returning clob to varchar from a stored procedure", version Oracle8.0.5/Sun OS

You Asked
Hi Tom,
The issue is to return the text details stored in a table as
clob(after
loaded into the table from a text file). Is there a limitation
like
4000 for the size of an OUT parameter to passed into a stored
procedure?

I have created the following stored procedure
create or replace procedure test_proc(myid number, mydoc out
varchar2) is
c_lob        clob;
myclob_text    varchar2(4000);
len        number:=0;
amount        number:=100;
offset        number;
begin

select theclob
into c_lob
from demo
where id=myid;

len := dbms_lob.getlength(c_lob);
offset := 1;
while (len > 0) loop
myclob_text := dbms_lob.substr (c_lob, amount, offset);

--        dbms_lob.read(c_lob, amt2, offset, myclob_text);
--        dbms_output.put_line (myclob_text);
len := len - amount;
offset := offset + amount;
mydoc := mydoc || myclob_text;
end loop;
end;
/

Testing using:
SQL> variable txt varchar2(4000);
SQL> exec test_proc(1, :txt);
Error: ORA-06502 PL/SQL: numeric or value error

Text in id 1 is loaded from a file size of 16K.
If I passed in the id=2 which contains 2 lines of text, it is
OK.

If I would like to call this stored procedure using thin
client JDBC calls, will it works for big clob?

What is the solution if I were to return the clob->varchar2 from

a stored procedure?

Thank you in advance

Regards,
Hwee


and we said...
There is a 32k LIMIT on the size of an OUT parameter (or IN
parameter or in fact all PLSQL variables).  The reason you are
getting

SQL> variable txt varchar2(4000);
SQL> exec test_proc(1, :txt);
Error: ORA-06502 PL/SQL: numeric or value error


is due to the fact that you are trying to stuff 16k of data into
4000 bytes of allocated space.  SQLPlus will not let you define
a variable of greater them 4000 bytes (but you can in other
languages).

Below shows that a plsql routine can in fact return 16k of data:

ops$tkyte@DEV8I.WORLD> create table t ( x int, y clob );

Table created.

ops$tkyte@DEV8I.WORLD>
ops$tkyte@DEV8I.WORLD> declare
2          tmp     long;
3          c       clob;
4  begin
5          tmp := rpad( '*', 16384, '*' );
6          insert into t values ( 1, empty_clob() )
returning y into c;
7          dbms_lob.writeappend( c, length(tmp), tmp );
8
9          tmp := rpad( '*', 2048, '*' );
10          insert into t values ( 2, empty_clob() )
returning y into c;
11          dbms_lob.writeappend( c, length(tmp), tmp );
12  end;
13  /

PL/SQL procedure successfully completed.

ops$tkyte@DEV8I.WORLD> select x, dbms_lob.getlength(y) from t
2  /

X DBMS_LOB.GETLENGTH(Y)
---------- ---------------------
1                 16384
2                  2048

ops$tkyte@DEV8I.WORLD> create or replace procedure test_proc(
myid number, mydoc OUT varchar2 )
2  as
3          l_clob  clob;
4  begin
5          select y into l_clob
6            from T
7           where x = myid;
8
9          mydoc := dbms_lob.substr( l_clob, 32765, 1 );
10  end;
11  /

Procedure created.

ops$tkyte@DEV8I.WORLD> declare
2          test_bind_variable long;
3  begin
4          test_proc( 1, test_bind_variable );
5          dbms_output.put_line( 'returned length is ' ||
length(test_bind_variable) );
6  end;
7  /
returned length is 16384

PL/SQL procedure successfully completed.

ops$tkyte@DEV8I.WORLD>

In Java, using the 8.1.5 thin driver, I coded the following:

import java.io.*;
import java.sql.*;
import java.util.*;

class test
{

public static void main(String args[])
{
Statement statement = null;

try
{
DriverManager.registerDriver
(new oracle.jdbc.driver.OracleDriver());

Connection connection =
DriverManager.getConnection
("jdbc:oracle:thin:@aria-dev:1521:ora8idev",
"scott", "tiger");

DatabaseMetaData conMD = connection.getMetaData();
System.out.println("JDBC Driver Name        :\t" +
conMD.getDriverName());
System.out.println("JDBC Driver Version     :\t" +
conMD.getDriverVersion());
System.out.println("Database Product Name   :\t" +
conMD.getDatabaseProductName());
System.out.println("Database Product Version:\t" +
conMD.getDatabaseProductVersion());
System.out.println("Max Statements          :\t" +
conMD.getMaxStatements());
System.out.println();

connection.setAutoCommit(false);

statement = connection.createStatement();

CallableStatement cstmt = connection.prepareCall(
"begin test_proc( 1, ? ); end;" );

cstmt.registerOutParameter( 1, java.sql.Types.CHAR );
System.out.println( "prepared & registered" );
cstmt.executeUpdate();

String newVal = cstmt.getString( 1 );
System.out.println
( newVal.length() + " bytes retrieved..." );

}
catch( Exception e )
{
e.printStackTrace();
}

}

}

and it returns:

$ java test
JDBC Driver Name        :       Oracle JDBC driver
JDBC Driver Version     :       8.1.5.0.0
Database Product Name   :       Oracle
Database Product Version:       Oracle8i Enterprise Edition
Release 8.1.5.0.0 - Production
With the Partitioning and Java options
PL/SQL Release 8.1.5.0.0 - Production
Max Statements          :       0

prepared & registered
16384 bytes retrieved...

So, you should be able to use this method to retrieve UPTO 32k
of text.  Beyond that you would have to use streams on the clobs.
Review & Followup

Rating: 5
Is there a 4k limit when returning a portion of a clob in a function? August 28, 2003
Reviewer: Anthony from ny
Tom,
I am trying to create a function to return a portion of a clob. The size is
greater than 4k but less than 10k.
I'm having some trouble understanding what's going on here:

create table t( a int, b date, c clob );

insert into t values( 1, sysdate, rpad('*',400,'*') );
commit;

create or replace function get_clob( p_ptr clob )
return varchar2
is
begin
return dbms_lob.substr( p_ptr, dbms_lob.getlength(p_ptr), 1 );
end;
/

/* test it out */
SQL> col text form a50
SQL> select a,b,get_clob(c) text from t;
A B         TEXT
---------- --------- --------------------------------------------------
1 28-AUG-03 **************************************************
**************************************************
**************************************************
**************************************************
...

so far so good. The return val is less than or equal to the SQL limit of 4k.

/* putting in a bigger clob */
declare
l_ptr clob;
begin
insert into t values( 2, sysdate, empty_clob() ) returning c into l_ptr;
dbms_lob.write( l_ptr, 32767, 1, rpad( '*',32767,'*' ) );
commit;
end;
/

SQL> select dbms_lob.getlength(c) from t;

DBMS_LOB.GETLENGTH(C)
---------------------
4000
32767

/* the following error is expected */
SQL> select a,b,get_clob(c) from t where a=2;
ERROR:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "SCOTT.GET_CLOB", line 5

/* but, this doesn't work.... */
SQL> declare
x varchar2(32767);
begin
select get_clob( c ) into x from t where a=2;
dbms_output.put_line(length(x));
end;
/
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "SCOTT.GET_CLOB", line 5
ORA-06512: at line 4

/* ...while this does */
SQL> declare
x varchar2(32767);
y clob;
begin
select c into y from t where a=2;
x := get_clob( y );
dbms_output.put_line( x );
end;
32767

PL/SQL procedure successfully completed.

Why does the last anonymous block succeed?
Is this first block doing it in SQL (even though it's in a pl/sql block),
therefore restricted to 4k as well?

Thanks in advance,
-Ant


Followup:
sql is limited to 4000 bytes unless you just return the CLOB/BLOB itself.

plsql is limited to 32k unless you return the clob/blob itself
Rating: 4
excellent February 20, 2004
Reviewer: vj from in
Hi,

The below is the version of oracle we are using

Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
PL/SQL Release 9.2.0.1.0 - Production
CORE 9.2.0.1.0 Production
TNS for 32-bit Windows: Version 9.2.0.1.0 - Production
NLSRTL Version 9.2.0.1.0 - Production

We have an SP that return (out param )the CLOB datatype to the calling
program.The calling program is an JSP and we use oracle thin driver. My size of
CLOB is around 32KB and sometimes little more than 32KB. If we send below 30kb
it is working, but if it is more than 30 KB it is not
working. Any other alternate as we built the programs around the same logic.

Rgds


Followup:
you'd really have to provide a teeny tiny code snippet for you can use clobs of
unlimited size in java/jdbc (well, upto the current 4gig limit in 9i).  You
would interface to them as "streams" -- perhaps you are using "strings"?

small
concise
yet complete

is the best test case.  it won't need a jsp to reproduce your issue -- a tiny
"main" with a tiny bit of code.
February 20, 2004 Ramasubbu -- Thanks for the question regarding "Cuncurrent execution of procedures", version Oracle8i Enterprise Edition Release 8.1.6.3.0 - Production
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: