How to solve : ORA-06502: PL/SQL: numeric or value error? - oracle

I have a long text in CLOB and I'm trying to use the function htp.prn
Here is my code :
n := dbms_lob.getlength(html); -- n is 31745 characters
if n<32000 then
htp.prn(HTML); -- << Error raised here
else
do something else
end if;
When using the function htp.prn, I'm getting the error : ORA-06502: PL/SQL: numeric or value error
I know he text size allowed is 32672 characters. And the text contains some chinese characters. So, I assume the problem is coming from dbms_lob.getlength
Does anyone know how to solve that please ?
Thanks
Cheers,

If you have Unicode characters (you mentioned Chinese), and your database is using a multibyte characterset, then the number of bytes is greater than the number of characters. 32767 is a hard limit of bytes. Whereas, dbms_lob.getlength for CLOBs and NCLOBs counts characters. So you probably are over the 32K limit in bytes.
You cannot easily get the length of a CLOB in bytes. There are various unpleasant workarounds, but probably the easiest thing for you to do is simply trap the exception rather than predict it:
n := dbms_lob.getlength(html);
if n<32000 then
declare
value_error exception;
pragma exception_init(value_error,-06502);
begin
htp.prn(HTML);
exception
when value_error then
null;
end;
else
do something else
end if;

Multibyte characters, eh?
Perhaps you could handle it by splitting that string into smaller chunks.
My example uses not that long string which is then split into 20 characters in length. I'm just displaying them (line #10); you'd htp.prn it (line #11).
SQL> set serveroutput on
SQL> declare
2 html clob := 'How to solve: ORA-06502: PL/SQL: numeric or value error';
3 l_var varchar2(20); --> you'd use e.g. 5000
4 l_size number := 20; --> you'd use e.g. 5000
5 l_pos number := 1;
6 begin
7 while dbms_lob.getlength(html) >= l_pos
8 loop
9 l_var := dbms_lob.substr(html, l_size, l_pos);
10 dbms_output.put_line(l_var);
11 htp.prn(l_var);
12 l_pos := l_pos + length(l_var);
13 end loop;
14 end;
15 /
How to solve: ORA-06
502: PL/SQL: numeric
or value error
PL/SQL procedure successfully completed.
SQL>

Related

ORA-06502 with ORA-06512

I have a procedure in which I'm trying to write a source code (1290 lines) to dbms_output like this:
dbms_output.put_line(DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner')); --MYPROC, line 6
I'm getting :
ORA-06502: PL/SQL: numeric or value error
ORA-06512: in "MYPROC", line 6
.
This error occures in toad.
I can execute in editor tab of toad:
SELECT DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner') FROM DUAL;
I mean I'm getting the source code in 'Data grid'.
Same happens when I try to store the code in a CLOB variable:
src CLOB;
...
src := DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner') ; --MYPROC, line 6
Any clue?
From the documentation for dbms_output:
The maximum line size is 32767 bytes.
That means that you can't pass more than that in a single put_line call. You are currently passing your whole CLOB, which at 1290 lines is likely to exceed that limit. And the error you get when you do that is "ORA-06502: PL/SQL: numeric or value error", as you are seeing.
You can split your CLOB into smaller chunks, and as it is already multiple lines it makes sense to make each chunk a single line from the DDL. You can do that by looking for newline characters, extracting all the text up to the next one, and printing that. You need a few variables to keep track of where you are. Something like this should work for you:
declare
src clob;
src_length pls_integer;
pos pls_integer := 1;
buffer varchar2(32767);
amount pls_integer := 32767;
begin
src := dbms_metadata.get_ddl('FUNCTION', 'TEST_FUNCTION_1', user);
src_length := dbms_lob.getlength(src);
while pos < src_length loop
-- read to next newline if there is one, rest of CLOB if not
if dbms_lob.instr(src, chr(10), pos) > 0 then
-- see how many charcaters there are until next newline
amount := dbms_lob.instr(src, chr(10), pos) - pos;
-- if there are any, read them into the buffer; otherwise clear it
if amount > 0 then
dbms_lob.read(src, amount, pos, buffer);
else
buffer := null;
end if;
pos := pos + amount + 1; -- skip newline character
else
-- no newline so read everything that is left
amount := 32767;
dbms_lob.read(src, amount, pos, buffer);
pos := pos + amount;
end if;
dbms_output.put_line(buffer);
end loop;
end;
/
It won't work if you have a single line (without or without a newline at the end) that is more than 32k, which hopefully won't be an issue with DDL. (You could sort of handle it, but doing so would inject additional newlines, which wouldn't be good either.)
What you are saying can't be true. DBMS_OUTPUT.PUT_LINE can't be used at SQL level, it belongs to PL/SQL.
What is MYPROC and what does it contain at line #6?
Which "editor" is "I can execute in editor"?
Numeric or value error is usually related to the fact that you're trying to store "large" values into a "small" variable:
SQL> declare
2 l_var varchar2(2);
3 begin
4 l_var := 'ABC';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4
SQL>
which is what - I presume - you did.
Another cause is wrongly declared variable, e.g.
SQL> declare
2 l_var number;
3 begin
4 l_var := 'A';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 4
SQL>
I'll try to guess what you might be doing:
SQL> set serveroutput on
SQL> DECLARE
2 src CLOB;
3 BEGIN
4 src := DBMS_METADATA.GET_DDL ('PACKAGE', 'MY_PKG', 'SCOTT');
5 DBMS_OUTPUT.put_line ('len = ' || DBMS_LOB.getlength (src));
6 END;
7 /
len = 67239
PL/SQL procedure successfully completed.
SQL>
As you can see, it works OK for me. Package isn't that small (see its length), so - can't really tell what you did wrong. I'd suggest you to do exactly as I did - copy/paste code I posted above (those 7 lines), fix information (function, its name, owner) and post the result by editing the original question, not as a comment.

pl-sql clob data issue

Hi getting below error
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause: An arithmetic, numeric, string, conversion, or constraint error
occurred. For example, this error occurs if an attempt is made to
assign the value NULL to a variable declared NOT NULL, or if an
attempt is made to assign an integer larger than 99 to a variable
declared NUMBER(2).
*Action: Change the data, how it is manipulated, or how it is declared so
that values do not violate constraints.
when i run the following pl-sql code
DECLARE
type c_list is varray (6000) of varchar2(50);
name_list c_list := c_list();
counter integer :=0;
n number;
ADDHDR VARCHAR2(5000);
new_envelope clob:=NULL;
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
FOR n in 1..1000 LOOP
counter := counter + 1;
name_list.extend;
name_list(counter) := 'ABCNDFHDDJJ';
dbms_output.put_line('Customer('||counter ||'):'||name_list(counter));
END LOOP;
for i in name_list.first .. name_list.last loop
ADDHDR := CONCAT(ADDHDR,'<ADDITIONAL_START>');
ADDHDR := CONCAT(ADDHDR, CONCAT('<START>', CONCAT('ADDR-KYC-ABCD-PRD-LDB-SMS-OR-START', '</START>')));
ADDHDR := CONCAT(ADDHDR, CONCAT('<ENDED>', CONCAT(name_list(i), '</ENDED>')));
ADDHDR := CONCAT(ADDHDR, '</ADDITIONAL_START>');
dbms_output.put_line('PROCESSING');
new_envelope := new_envelope || ADDHDR;
ADDHDR:=''
end loop;
dbms_output.put_line(new_envelope);
END;
/
please help me to concat string(value greater than 4000 characters) to a clob data
Thanks in advance
Problem is this line dbms_output.put_line(new_envelope);
You cannot output such large strings. I assume this is just for debugging, i.e. actually not needed.
If you really need dbms_output.put_line then do it line by line.

Oracle - ORA-06502: PL/SQL: numeric or value error (DBMS_OUTPUT)

I implemented a function that returns clob data-type, and I would like to print the result in DBMS Output. Unfortunately, I am getting ORA-06502: PL/SQL: numeric or value error and I think it is due to the size of DBMS_OUTPUT.
This is the code.
DECLARE
TYPE tp_col_array IS TABLE OF varchar2(32767);
FUNCTION my_fn (
p_in_proc_date IN varchar2)
RETURN clob AS
vr_output_str clob;
BEGIN
-- Detailed code hidden due to privacy. Sorry
RETURN vr_output_str;
EXCEPTION
WHEN LOGIN_DENIED
THEN
DBMS_OUTPUT.PUT_LINE('Invalid username/password: logon denied');
RETURN 'TEST Terminated';
END my_fn;
BEGIN
DBMS_OUTPUT.PUT_LINE(my_fn('31-AUG-14'));
END;
Here are something that can help you to understand this issue
1) Added the following to set the size of buffer unlimited, but did not work..
DBMS_OUTPUT.ENABLE(NULL);
or
set serveroutput on size unlimited;
Related link: http://www.oracle-developer.net/display.php?id=327
2) It is noted that the size of vr_output_str is 75387, and that is why the return type is CLOB.
DBMS_LOB.getlength(vr_output_str); // =75387
3) I can solve the issue by doing the following, but I think this is not a good solution since it executed the function three times.
DBMS_OUTPUT.PUT_LINE(SUBSTR(my_fn ('31-AUG-14'), 1, 32767));
DBMS_OUTPUT.PUT_LINE(SUBSTR(my_fn ('31-AUG-14'), 32768, 32767));
DBMS_OUTPUT.PUT_LINE(SUBSTR(my_fn ('31-AUG-14'), 65536, 32767));
4) I am using Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
You will not be able to print a clob using dbms_output.put_line directly if it is greater than 32767 bytes.
If this is the case you can create a procedure to iterate through the clob and print out one smaller chunk at a time. Such a procedure and test script is below:
declare
c clob;
procedure print_clob( p_clob in clob ) is
v_offset number default 1;
v_chunk_size number := 10000;
begin
loop
exit when v_offset > dbms_lob.getlength(p_clob);
dbms_output.put_line( dbms_lob.substr( p_clob, v_chunk_size, v_offset ) );
v_offset := v_offset + v_chunk_size;
end loop;
end print_clob;
begin
for i in 1..10000 loop
c := c || 'test';
end loop;
--This will result in ora-06502
--dbms_output.put_line(c);
print_clob(c);
end;
Note that v_chunk_size must result in less than 32767 bytes being chunked at-a-time. If you encoding has 2 bytes per char you will need to use (32767/2).
The following procedure will better:
Oracle 10g has limitation on put_line (a maximum of 32767 characters), But Oracle before 10g has a maximum of 255 characters limitation.
the 'put_line' adding end of line on every iteration loop during output clob. So we use put() better (and 'DBMS_OUTPUT.NEW_LINE' at end).
PROCEDURE print_clob( p_clob in clob ) IS
v_offset number default 1;
v_chunk_size number := 255;
BEGIN
LOOP
EXIT when v_offset > dbms_lob.getlength(p_clob);
dbms_output.put( dbms_lob.substr( p_clob, v_chunk_size, v_offset ) );
v_offset := v_offset + v_chunk_size;
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END print_clob;

To_CHAR result cannot go in VARCHAR2

There is somthing strange I wouls like to understand
let's say we have this code :
DECLARE
a varchar2(6);
BEGIN
a := '000001';
END;
This works good. No problem
Now we have this :
DECLARE
a varchar2(6);
BEGIN
a := TO_CHAR(1, '000000');
END;
It does not work:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
why?
A problem with nls_language maybe? what problem? what solution?
Thank you
The TO_CHAR result has a space at the beginning, making its total length 7 characters. The space is reserved for a minus sign if the number is negative. If you try this query you'll see:
SELECT '[' || TO_CHAR(1, '000000') || ']' FROM DUAL;
The result is:
[ 000001]
^ space for a minus sign
To get the result without the space, use the FM modifier:
a := TO_CHAR(1, 'FM000000');
Or, just use `LTRIM' :
SQL> set serveroutput on;
SQL> DECLARE
2 a VARCHAR2(6);
3 BEGIN
4 A := LTRIM(TO_CHAR(1, '000000'));
5 dbms_output.put_line(a);
6 END;
7 /
000001
PL/SQL procedure successfully completed.
SQL>
Note that a leading blank only appears before a positive number with no sign formatting. No leading blank appears before a negative number, or before any signed number, regardless of the placement of the sign.
The “FM” format to override the default leading blank for unsigned positive numbers

Oracle - Number to varchar

I have a table containing a column of type Number
create table tmp (
/*other fields*/
some_field Number
)
and in a PL SQL script, I want to convert that field to a varchar. However, i don't know its length, so I get an exception
Exception message is ORA-06502:
PL/SQL: numeric or value error:
character string buffer too small
v_some_field varchar(21);
/*...*/
v_some_field := TO_CHAR(some_field,'999999999999999999999');
How should i declare the v_some_field buffer? Setting it to varchar(32767) seems quite brute, is there any alternative?
you're getting an error not because the number is too large but because the result of your to_char is 22 characters long (21x"9"+one character for the sign):
SQL> DECLARE
2 some_field NUMBER := 123;
3 v_some_field VARCHAR(21);
4 BEGIN
5 v_some_field := TO_CHAR(some_field, '999999999999999999999');
6 END;
7 /
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
SQL> DECLARE
2 some_field NUMBER := 123;
3 v_some_field VARCHAR(22);
4 BEGIN
5 v_some_field := TO_CHAR(some_field, '999999999999999999999');
6 END;
7 /
PL/SQL procedure successfully completed
You could determine the maximum length of your converted varchar2 by converting a negative value with integral and fractional digits:
set serveroutput on
declare
n number;
begin
n := -4/3;
dbms_output.put_line(length(to_char(n)));
end;
/
Output is 41 for me.

Resources