How to execute Oracle procedure with clob parameter in? - oracle

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';

Related

PLSQL dynamically truncate string to varchar2 column size

I'm looking for a way to dynamically truncate a string to the max size of a varchar2 column.
See example below.
Table definition
CREATE TABLE some_table
(
log varchar2(50)
);
Code
DECLARE
v_str some_table.log%TYPE;
BEGIN
v_str := SUBSTR('a text longer than 50 chars ...', 1, 50 /*HOW TO GET 50 DYNAMICALLY HERE ?*/ );
END;
Any ideas?
select char_length
from user_tab_columns
where table_name = 'SOME_TABLE'
and column_name = 'LOG';
would return a value of 50 (the length of the log column in the some_table table)
Getting (and caching) the column length is probably the way to go, but just for fun and riffing from an approach in this discussion:
DECLARE
v_str some_table.log%TYPE;
v_ret pls_integer;
v_len pls_integer;
BEGIN
v_ret := anydata.convertchar('-').getchar(v_str);
v_len := length(v_str);
dbms_output.put_line(v_len);
v_str := substr('a text longer than 50 chars, a text longer than 50 chars, a text longer than 50 chars...', 1, v_len);
dbms_output.put_line(v_str);
END;
/
dbms_output:
50
a text longer than 50 chars, a text longer than 50
Because it's using convertchar and getchar rather than the varchar2 versions, the result is the literal char - padded to its maximum length based on the variable's data type.
db<>fiddle
You can read more about anydata at Oracle-base or in the documentation.
You could still cache that, or work it out on exception. If you were going to do this often and performance was acceptable without caching/catching, you could possibly wrap it in a procedure:
CREATE PROCEDURE trunc_string(p_str out varchar2, p_val varchar2)
AS
v_ret pls_integer;
v_len pls_integer;
BEGIN
v_ret := anydata.convertchar('-').getchar(p_str);
v_len := length(p_str);
p_str := substr(p_val, 1, v_len);
END;
/
and then call that as:
DECLARE
v_str1 some_table.log%TYPE;
v_str2 varchar2(30);
BEGIN
trunc_string(v_str1, 'a text longer than 50 chars, a text longer than 50 chars, a text longer than 50 chars...');
dbms_output.put_line(v_str1);
trunc_string(v_str2, 'a text longer than 30 chars, a text longer than 30 chars, a text longer than 30 chars...');
dbms_output.put_line(v_str2);
END;
/
dbms_output:
a text longer than 50 chars, a text longer than 50
a text longer than 30 chars, a
db<>fiddle
But that's probably overkill... though that could be said about using anydata at all.

ORA-06502: PL/SQL: numeric or value error: character string buffer too small, Using shell script

I saw a lot of answers for the same query but didn't find any issue with my code. I am getting this error in declare block. p_pid is process id which is 4 digit long.Just for information I am using bash scripts to pass some parameters to sql blocks.
PL/Sql Block
declare
v_errorseq number := ${p_pid};
begin
log_table_pkg.set_stamp_num(v_errorseq);
log_table_pkg
gv_stamp_num number;
gv_host_name varchar2;
gv_seq_num varchar2;
procedure set_stamp_num(p_stamp_num number)
is
begin
if p_stamp_num is null
then
raise_application_error(-20001,'Null stamp number.');
end if;
gv_stamp_num := p_stamp_num;
end;

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 12c CLOB data type is not working as expected

I have This Oracle 12c Procedure
CREATE OR REPLACE PROCEDURE LOGINCHECK(SQLQRY IN CLOB)
AS
C INTEGER;
N INTEGER;
RC SYS_REFCURSOR;
stmt clob:= To_Clob('begin ' || sqlqry || '; end;');
BEGIN
C := SYS.DBMS_SQL.OPEN_CURSOR;
SYS.DBMS_SQL.PARSE(C,stmt ,DBMS_SQL.native);
N := SYS.DBMS_SQL.EXECUTE(C);
SYS.DBMS_SQL.GET_NEXT_RESULT(C,RC);
SYS.DBMS_SQL.RETURN_RESULT(RC);
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
when OTHERS then
RAISE;
END LOGINCHECK;
I Call This Procedure in Anonymous Block Like This (Download XML Data from here: Link)
declare stmt clob := 'INWARDPKG.MACHINEINWARD_VALIDATING(XMLDOC => XMLTYPE.CREATEXML(paste xml from link))'; --The parameter value is a xml you can download it from above link
begin
LOGINCHECK(SQLQRY => STMT);
end;
But I am getting Error PLS-00172: string literal too long.
If i reduce xml size to 40-50 elements like remove some elements. this works fine.
In your first line declare stmt clob := 'INWARDPKG.MACHINEINWARD_VALIDATING... you are defining your CLOB. Since you are using a string literal to define your CLOB, you are facing the limits of string literals (see Oracle 12c Documenation).
To solve your problem you have to build your CLOB step by step, using the DBMS_LOB package and appending strings not longer than 4000 bytes until your CLOB is complete.
The basic idea:
DECLARE
C CLOB := TO_CLOB('First 4000 bytes');
V VARCHAR2(4000);
BEGIN
V := 'Next 4000 bytes';
DBMS_LOB.WRITEAPPEND(C, LENGTH(V), V);
-- more WRITEAPPEND calls until C is complete
DBMS_OUTPUT.PUT_LINE('CLOB-Length: ' || DBMS_LOB.GETLENGTH(C));
END;

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