To_CHAR result cannot go in VARCHAR2 - oracle

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

Related

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

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>

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 String Validation

I am trying to write a script that prompts for a input and it should validate if the given input has 19 characters;the first 3 characters must be 'ABC' followed by 16 characters(combination of alphabets and numbers)...
def mch_id='&1'
declare
chk_var varchar2(200) := '&mch_id';
begin
IF chk_var like'ABC_____________' then
dbms_output.put_line('correct');
else
dbms_output.put_line('incorrect');
end if;
end;
Expected Output :
ABC5678GVTC438755RW43 - correct
ADSE4NJ8GGFT5FVNOKNHY - incorrect
Your comparison string is only 16 characters long, ABC and 13 underscores. You need 16 underscores to follow ABC according to your specification.
EDIT: As HepC notes below, even after fixing the number of underscores, you may still get incorrect answers. This is because the underscore stands for ANY character, not only for alpha or numeric.
Try this instead:
... if regexp_like(chk_var, '^ABC[[:alnum:]]{16}$') then...
This evaluates as TRUE if and only if chk_var matches
from the beginning of the string (the ^ marker)
the letters A, B, C in order
any alpha or numeric character (the outer [...] means any single character in the list provided within [...]; inside it, [:alnum:] is shorthand for any alpha or numeric character)
exactly 16 occurrences of "a single alnum character" (the 16 characters may be different from each other) (the {16} marker)
and the end of the string right after that (the $ marker).
Sample SQL*Plus session (screenshot):
SQL> set serveroutput on
SQL> define mch_id = 'ABC1234567812345678'
SQL> declare
2 chk_var varchar2(200) := '&mch_id';
3 begin
4 if regexp_like(chk_var, '^ABC[[:alnum:]]{16}$') then
5 dbms_output.put_line('correct');
6 else
7 dbms_output.put_line('incorrect');
8 end if;
9 end;
10 /
old 2: chk_var varchar2(200) := '&mch_id';
new 2: chk_var varchar2(200) := 'ABC1234567812345678';
correct
PL/SQL procedure successfully completed.
SQL> define mch_id = 'ABC123456781234%%%%'
SQL> /
old 2: chk_var varchar2(200) := '&mch_id';
new 2: chk_var varchar2(200) := 'ABC123456781234%%%%';
incorrect
PL/SQL procedure successfully completed.

Error : ORA-01704: string literal too long

While I try to set the value of over 4000 characters on a field that has data type CLOB, it gives me this error :
ORA-01704: string literal too long.
Any suggestion, which data type would be applicable for me if I have to set value of unlimited characters although for my case, it happens to be of about 15000 chars.
Note : The long string that I am trying to store is encoded in ANSI.
What are you using when operate with CLOB?
In all events you can do it with PL/SQL
DECLARE
str varchar2(32767);
BEGIN
str := 'Very-very-...-very-very-very-very-very-very long string value';
update t1 set col1 = str;
END;
/
Proof link on SQLFiddle
Try to split the characters into multiple chunks like the query below and try:
Insert into table (clob_column) values ( to_clob( 'chunk 1' ) || to_clob( 'chunk 2' ) );
It worked for me.
To solve this issue on my side, I had to use a combo of what was already proposed there
DECLARE
chunk1 CLOB; chunk2 CLOB; chunk3 CLOB;
BEGIN
chunk1 := 'very long literal part 1';
chunk2 := 'very long literal part 2';
chunk3 := 'very long literal part 3';
INSERT INTO table (MY_CLOB)
SELECT ( chunk1 || chunk2 || chunk3 ) FROM dual;
END;
Hope this helps.
The split work until 4000 chars depending on the characters that you are inserting. If you are inserting special characters it can fail.
The only secure way is to declare a variable.
Though its a very old question but i think sharing experience still might help others:
Large text can be saved in a single query if we break-down it in chunks of 4000 bytes/characters by concatinating them using '||'
Running following query will tell you:
Required Number of chunks containing 4000 bytes
Remaining bytes
Since, in given example you are trying to save text contining 15000 bytes (characters), so,
select 15000/4000 chunk,mod(15000,4000) remaining_bytes from dual;
Result:
That means, you need to concatenate 3 chunks of 4000 bytes and one chunk of 3000 bytes, so it would be like:
INSERT INTO <YOUR_TABLE>
VALUES (TO_CLOB('<1st_4K_bytes>') ||
TO_CLOB('<2nd_4K_bytes>') ||
TO_CLOB('<3rd_4K_bytes>') ||
TO_CLOB('<last_3K_bytes>)');
create a function that return a clob
create function ret_long_chars return clob is
begin
return to_clob('put here long characters');
end;
update table set column = ret_long_chars;
INSERT INTO table(clob_column) SELECT TO_CLOB(q'[chunk1]') || TO_CLOB(q'[chunk2]') ||
TO_CLOB(q'[chunk3]') || TO_CLOB(q'[chunk4]') FROM DUAL;
Accepted answer did not work for me in sql developper but combination of this answer and another one did :
DECLARE
str varchar2(32767);
BEGIN
update table set column = to_clob('Very-very-...-very-very-very-very-very-very long string value');
END;
/

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