pl-sql clob data issue - oracle

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.

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.

How to get the declared size of a varchar2 in oracle database

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;

Oracle RawToHex function - what happens if return value exceeds varchar2 limit?

The RawToHex function in Oracle 11g returns a hexadecimal representation of any raw value.
This function returns the Hex Value as a varchar2.
What happens if I pass a BLOB into the RawToHex() function that will result in a hex representation that exceeds the varchar2 limit of 4000?
Is there any way to convert very big BLOBs into a Hex representation?
UPDATE:
I did some investigation and found an answer for the first part of my question.
I can pass a BLOB into the RawToHex function and this one will execute successfully as long as you won't hit the boundaries of the Raw DataType. Oracle seems to convert from BLOB to Raw implicitly.
DECLARE
a varchar2(32767);
b blob;
BEGIN
select blob_column into b from a_table where a_table_id = 1;
dbms_output.put_line(dbms_lob.getlength(b)); --> output: 216
dbms_output.put_line(rawtohex(empty_blob())); --> converted blob
select blob_column into b from a_table where a_table_id = 2;
dbms_output.put_line(dbms_lob.getlength(b)); --> output: 140000
dbms_output.put_line(rawtohex(empty_blob())); --> ORA-06502: PL/SQL: numeric or value error
END;
Description of this error according to ora-code.com
ORA-06502: PL/SQL: numeric or value error string
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.
UPDATE 2:
I've got a solution for this issue. Splitting the blob into smaller blocks and converting them step by step. It delivers the correct result. Is this a correct approach or could this solution fall over at some point?
function BlobToHex(data in blob) return clob
is
v_clob clob;
v_start pls_integer := 1;
v_buffer pls_integer := 4000;
begin
if data is null
then
return '""';
end if;
dbms_lob.createtemporary(v_clob, true);
dbms_lob.append(v_clob, '0x');
for i in 1..ceil(dbms_lob.getlength(data) / v_buffer)
loop
dbms_lob.append(v_clob, rawtohex(DBMS_LOB.SUBSTR(data, v_buffer, v_start)));
v_start := v_start + v_buffer;
end loop;
return v_clob;
end;
You'll get ORA-00932
SQL> select rawtohex(empty_blob()) from dual;
select rawtohex(empty_blob()) from dual
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected - got BLOB
SQL>
because
As a SQL built-in function, RAWTOHEX accepts an argument of any scalar data type other than LONG, LONG RAW, CLOB, BLOB, or BFILE.
As stated by the documentation.

Pl/SQL: How to sort a table of records?

I'm new to pl/sql !
I'm trying to sort a table of records, using a simple bubble-sort algorithm. What is the problem?
Where could I find more information about using table of records ?
DECLARE
text VARCHAR2(50);
TYPE TIP_VECTOR
IS
TABLE OF INT INDEX BY BINARY_INTEGER;
TYPE contorRecord
IS
record
(
codASCII VARCHAR2(3),
contor SMALLINT);
TYpe tip_vector2
IS
TABLE OF contorRecord;
VECTOR TIP_VECTOR;
VECTOR2 TIP_VECTOR2 := TIP_VECTOR2();
aux tip_vector2 := tip_vector2();
v_char VARCHAR2(3);
FLAG BOOLEAN := TRUE;
t smallint;
n SMALLINT := 1;
ind SMALLINT := 0;
begin
AUX.EXTEND(1);
WHILE(FLAG)
LOOP
FLAG := FALSE;
-- here is the problem; what i'm doing wrong?
FOR I IN 1..(vector2.count-1) LOOP
-- here is the problem; what i'm doing wrong?
IF VECTOR2(I).CONTOR < VECTOR2(I+1).contor THEN
AUX := VECTOR(I+1);
VECTOR(i+1) := VECTOR(I);
VECTOR(I) := AUX;
FLAG := TRUE;
END IF;
END LOOP;
END LOOP;
end;
Error:
Error report:
PLS-00382: expression is of wrong type
PL/SQL: Statement ignored
PLS-00382: expression is of wrong type
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Here's a nice technique if you do not want to roll-your-own: http://technology.amis.nl/blog/1217/sorting-plsql-collections-the-quite-simple-way-part-two-have-the-sql-engine-do-the-heavy-lifting
Also it's perhaps not the way you really need. Generally you can benefit from using SQL in PL/SQL code - in SQL you can just ORDER BY your results. What's the problem you're trying to solve?
Information on PL/SQL collections is available here: PL/SQL Language Reference
You have your types and variables mixed up. Try:
DECLARE
TYPE contorRecord IS record ( codASCII VARCHAR2(3), contor SMALLINT);
TYpe tip_vector2 IS TABLE OF contorRecord;
VECTOR2 TIP_VECTOR2 := TIP_VECTOR2();
aux contorRecord;
FLAG BOOLEAN := TRUE;
begin
WHILE(FLAG)
LOOP
FLAG := FALSE;
FOR I IN 1..(vector2.count-1) LOOP
IF VECTOR2(I).CONTOR < VECTOR2(I+1).contor THEN
AUX := VECTOR2(I+1);
VECTOR2(i+1) := VECTOR2(I);
VECTOR2(I) := AUX;
FLAG := TRUE;
END IF;
END LOOP;
END LOOP;
end;
/
(Tidied up by removing all unused types and variables)

Resources