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

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;

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.

ORA-06502 while dbms_sql.execute(<anonymous block>) with out-binding

I got some trouble with executing dynamic SQL with binding variables (in and out) via dbms_sql.
I always get an ORA-06502 but cannot get the reason.
I could reduce the SQL-snippet so far to know that the out parameter occurs the error.
declare
l_cur_id NUMBER;
l_sql VARCHAR2(100) := 'begin :1 := ''test''; end;';
l_res VARCHAR2(100);
l_dbms NUMBER;
begin
l_cur_id := dbms_sql.open_cursor;
dbms_sql.parse(l_cur_id, l_sql, dbms_sql.native);
dbms_sql.bind_variable(l_cur_id, '1', l_res);
l_dbms := dbms_sql.execute(l_cur_id); -- ORA here
dbms_sql.close_cursor(l_cur_id);
exception
when others then
dbms_sql.close_cursor(l_cur_id);
raise;
end;
/
In-parameters work fine.
I'm using Oracle Database 12 Enterprise Edition Release 12.1.0.2.0
Do I have to config the out-parameter in another way?
I'm thankful for any help.
You haven't specified a size for the bind variable. By default it uses the current length of the variable; from the documentation:
Parameter
Description
out_value_size
Maximum expected OUT value size, in bytes, for the VARCHAR2, RAW, CHAR OUT or IN/OUT variable. If no size is given, then the length of the current value is used. This parameter must be specified if the value parameter is not initialized.
As that variable is by default initialised as null, that length is zero; which is the same as saying it isn't initialised. So it errors when it tries to assign the four-character 'test' to to the zero-character variable.
You also need to call dbms_sql.variable_value to get retrieve the out bind variable value.
If you initialised l_res with a value at least as long as anything you might assign inside the dynamic block then it would work:
declare
...
l_res VARCHAR2(100) := 'xxxx';
...
begin
...
dbms_sql.bind_variable(l_cur_id, '1', l_res);
l_dbms := dbms_sql.execute(l_cur_id);
dbms_sql.variable_value(l_cur_id, '1', l_res);
...
end;
/
but that obviously ideal, as really you'd need to supply a value 100-chars long, and remember to adjust that if the length changed later; so instead specify the length in the bind call:
declare
...
l_res VARCHAR2(100);
...
begin
...
dbms_sql.bind_variable(l_cur_id, '1', l_res, 100);
l_dbms := dbms_sql.execute(l_cur_id);
dbms_sql.variable_value(l_cur_id, '1', l_res);
...
end;
/
db<>fiddle

How to execute Oracle procedure with clob parameter in?

I have a procedure
create or replace PROCEDURE PROC_PROJPREL_TEMPL_SERV_MAT(
P_TABELA IN VARCHAR2,
P_COLUNAS IN VARCHAR2,
P_DADOS IN CLOB,
O_CODIGO OUT NUMBER,
O_MENSAGEM OUT VARCHAR2
) IS
BEGIN
o_codigo := 0;
o_mensagem := '';
-- no implementation coded yet
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20101, 'erro ao executar procedure ');
END PROC_PROJPREL_TEMPL_SERV_MAT;
And I need to execute this in SQL Developer.
I tried using anonymous block
declare
i_tabela varchar2(30);
i_colunas varchar2(4000);
i_dados clob;
o_codigo number;
o_mensagem varchar2(4000);
begin
i_tabela := 'table_name'; -- max 30 characters
i_colunas := 'columns_names'; -- less 4000 characters
i_dados := '45000 characters';
proc_projprel_templ_serv_mat(i_tabela, i_colunas, i_dados, o_codigo, o_mensagem);
end;
But it returns an error "string literal too long"
and I tried using "call" command too.
call proc_projprel_templ_serv_mat('table_name', 'columns_names', &DATAS);
But it returns an error ORA-00972 identifier is too long, Cause: An identifier with more than 30 characters was specified, Action: Specify at most 30 characters.
Somebody can help me?
The maximum length of a string literal in PL/SQL is 32,767 characters. As the error "string literal too long" is saying, you're blowing out this limit here:
i_dados := '45000 characters';
You have to break up that string into sections up to 32,767 characters long and concatenate them together, e.g.:
i_dados := 'first 32767 characters' ||
'remaining 12233 characters';

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.

Not able to pass CLOB in Oracle function

I'm trying to pass CLOB as input parameter in oracle function. The function is created successfully, but when I try to pass a lengthy string, it gives
ora-01704 string literal too long
error.
Below is my function:
CREATE OR REPLACE FUNCTION mySchema.TESTFUNCTION(myData IN CLOB)
RETURN INT
AS
BEGIN
DBMS_OUTPUT.PUT_LINE(myData);
RETURN 1;
END;
When I try to call this function by passing lengthy string more than 5000 characters, it gives the error.
Can anybody help please
yes, I pass as a string only. Eg: select TESTFUNCTION('more than 5000 chars') from dual;
No, it cannot be done like that. That error is the expected one, simply because SQL(Oracle versions prior to 12c) cannot handle character literals that are more than 4000 bytes in length.
If you need to test your function use PL/SQL, where character literal can be up to 32767 characters(single byte character set) in length:
Here is our function:
Note: Starting from Oracle 10g R2 dbms_output.put_line() line limit is 32767 bytes, in versions prior to 10g R2 the line limit is 255 bytes.
create or replace function f1(
p_clob in clob
) return number is
begin
dbms_output.put_line(p_clob);
return 1;
end;
Here is our anonymous PL/SQL block to test that function:
clear screen;
set serveroutput on;
declare
l_var clob;
l_res number;
begin
l_var := 'aaaaaaaaaaaaaaaaaa.. more than 5000 characters';
l_res := f1(l_var);
end;
Result:
anonymous block completed
aaaaaaaaaaaaaaaaaa.. more than 5000 characters

Resources