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.
Related
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>
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.
Trying to get the size of a defined variable in Oracle. I may need to use a number when declaring the size of a varchar2 but would rather not have to keep track of an extra variable or number.
example pseudo code:
declare
myvar varchar(42) := 'a';
begin
/* I know the length is length(myvar) = 1. */
/* but how do I get 42? */
/* What is the max defined size of this variable */
declared_size_of(myvar);
end
The reason I need this is to lpad the length of the string to the declared size so it doesn't generate an exception.
As #Justin said in his comments, you don't have to explicitly blank pad the string if you use CHAR data type. Oracle would blank-pad the value to it's maximum size.
From documentation,
If the data type of the receiver is CHAR, PL/SQL blank-pads the value
to the maximum size. Information about trailing blanks in the original
value is lost.
For example,
SQL> SET serveroutput ON
SQL> DECLARE
2 myvar CHAR(42);
3 BEGIN
4 myvar:='a';
5 dbms_output.put_line(LENGTH(myvar));
6 END;
7 /
42
PL/SQL procedure successfully completed.
SQL>
Brute Force technique using exception handling which is probably very inefficient:
DECLARE
myvar varchar2(42) := 'a'; /* using varchar */
v_size number := null;
x varchar(4000) := '';
v_length number := 0;
BEGIN
begin
v_length := length(myvar);
x := myvar;
FOR i in v_length..8001 LOOP
myvar := myvar || ' '; /* add one space at a time until it causes an exception */
End Loop;
EXCEPTION
-- WHEN NO_DATA_FOUND THEN
WHEN OTHERS THEN
v_length := length(myvar);
end;
dbms_output.put_line('Declared size is varchar('||v_length
||') and length(myvar) is '||length(trim(myvar)));
END;
To fetch the max. of a column input, you simply could do:
SELECT MAX(LENGTH(Column))
FROM TableA;
ORA-06550: line 2, column 11:
PLS-00103: Encountered the symbol "=" when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table long double ref
char time timestamp interval date binary national character
nchar
The symbol "<an identifier>" was substituted for "=" to continue.
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Here is the code:
SET SERVEROUTPUT ON;
clear scr;
DECLARE v_counter := 0;
BEGIN
LOOP
v_counter:= v_counter+1;
IF v_counter=3 THEN CONTINUE; END IF;
EXIT WHEN v_counter=5;
END LOOP;
DBMS_OUTPUT.PUT_LINE('v_counter='||v_counter);
END;
Creating a anonymous block to display 1 to 5 and getting the below error
Your code will never display 1 to 5. As #David said in the comments -
You haven't declared the data type for the variable.
The DBMS_OUTPUT is outside the LOOP, thus it will print only the last value held by the variable.
That IF-ELSE construct seems unnecessary if you just want to print 1 to 5.
You could achieve the same in just one FOR LOOP -
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 FOR i IN 1..5
3 LOOP
4 DBMS_OUTPUT.PUT_LINE('v_counter='||i);
5 END LOOP;
6 END;
7 /
v_counter=1
v_counter=2
v_counter=3
v_counter=4
v_counter=5
PL/SQL procedure successfully completed.
SQL>
The same could be done in SQL -
SQL> select 'v_counter ='||level counter from dual connect by level <=5;
COUNTER
---------------------------------------------------
v_counter =1
v_counter =2
v_counter =3
v_counter =4
v_counter =5
SQL>
The problem is the line reading
DECLARE v_counter := 0;
You forgot to specify the variable's datatype.
It should read
DECLARE v_counter number := 0;
Of course, instead of number you might choose pls_integer if you're more confortable with it.
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.