ORA-06502 Numerical OR Value Error CHARACTER STRING BUFFER TO SMALL - oracle

Oracle Function Giving Me Error while i execute this function . it will give an error like character buffer value is too small at line no 20
CREATE OR REPLACE FUNCTION Fn_Lov_Purchase_Return (vComp_Id NUMBER,
vLoc_Id NUMBER,
vLIne_No NUMBER,
vParam NUMBER,
vAtt_Para NUMBER,
vLot_No VARCHAR2,
vDept_Id NUMBER)
RETURN VARCHAR2
AS
vPURC_NO VARCHAR2 (20000);
CURSOR c1
IS
SELECT M.DOC_NO AS PURC_NO
FROM RJN_GRN_TRANS_ITEMS I, RJN_GRN_TRANS_MASTER M
WHERE I.TRANS_ID = M.TRANS_ID
AND M.TRANS_TYPE = 'GRN'
AND M.COMP_ID = vComp_Id
AND M.COMP_ID = vLoc_Id
AND I.LINE_NO = vLIne_No
AND I.PARAMETER_CODE = vParam
AND I.ATT_PARAMETER_CODE = vAtt_Para
--AND I.LOT_NO= vLot_No
AND M.DEPT_ID = VDept_Id;
c1_Rec c1%ROWTYPE;
BEGIN
vPURC_NO := ' ';
FOR c1_Rec IN c1
LOOP
IF (vPURC_NO) = ' '
THEN
vPURC_NO := c1_Rec.PURC_NO;
ELSE
vPURC_NO := vPURC_NO || ', ' || c1_rec.PURC_NO;
END IF;
END LOOP;
RETURN (vPURC_NO);
EXCEPTION
WHEN NO_DATA_FOUND
THEN
vPURC_NO := 'No-Records';
RETURN vPURC_NO;
END;
/

If vPURC_NO VARCHAR2 (20000); isn't large enough, either make it larger, or use a CLOB data type.

Related

how to pass formatted string to column and same fetch it in package in PL/SQL

I have error master table which contain description like 'Error in table abc in xyz column.' I need to format string for column name which is xyz here. Where ever I need to call this table I will pass column name and then I will get expected description.
Ex - Insert into errorTabl values(01,There is error in {0})
Whenever inside package I need to retrieve value of 01 then I will pass column name col1 so then expected value will be as below :
01 There is error in col1
Request you to please help me for insert and select both statements.
Though this doesn't make sense, maybe the code below could help you to start with something or to clarify your problem.
NOTE: the code below is here just to show you the basics - there is no sense in it for any kind of production. You are the one to adjust it to your context.
So, the package to put and get things into or from errors table:
CREATE OR REPLACE PACKAGE ERRS AS
Procedure putError(p_table IN VarChar2, p_column IN VarChar2);
Function getError(p_table VarChar2, p_column VarChar2) RETURN VarChar2;
END ERRS;
-- ---------------------------------------------------------------------------------
CREATE OR REPLACE PACKAGE BODY ERRS AS
Procedure putError(p_table IN VarChar2, p_column IN VarChar2) AS
BEGIN
Declare
mSql VarChar2(512) := '';
sq VarChar2(1) := '''';
Begin
mSql := 'Insert Into ERRORTABLE values( ' || sq || '01' || sq || ', ' || sq ||
'There is error in table ' || p_table || ' in ' || p_column || ' column' || sq || ')';
Execute Immediate mSql;
Commit;
End;
END putError;
-- -------------------------------------------------------------------------------
Function getError(p_table VarChar2, p_column VarChar2) RETURN VarChar2 IS
BEGIN
Declare
Cursor c IS
Select ERR_DESC From ERRORTABLE Where ERR_DESC Like('%table ' || p_table || ' in ' || p_column || '%');
mRet VarChar2(512) := '';
mDesc VarChar2(512) := '';
Begin
Open c;
LOOP
FETCH c into mDesc;
EXIT WHEN c%NOTFOUND;
mRet := '01 ' || mDesc || Chr(10);
END LOOP;
Close c;
RETURN RTRIM(mRet, Chr(10));
End;
END getError;
END ERRS;
Now the calling code to insert 5 records (once more - this is senseless) and to get you one of them...
set serveroutput on
DECLARE
errMsg VarChar2(512);
BEGIN
ERRS.putError('T_ABC', 'C_XYZ');
ERRS.putError('T_ABC', 'C_MNO');
ERRS.putError('T_ABC', 'C_PQR');
ERRS.putError('T_DEF', 'C_MNO');
ERRS.putError('T_DEF', 'C_XYZ');
--
errMsg := ERRS.getError('T_ABC', 'C_XYZ');
dbms_output.put_line(errMsg);
END;
/* R e s u l t :
anonymous block completed
01There is error in table T_ABC in C_XYZ column
*/
Just needed to pass double colon in insert query so then it will take single colon in table.
Ex - Insert into errorTabl values(01,There is error in ''{0}'')
In table it will be look like
**Id** **Description**
01 There is error in'{0}'.

small string buffer for a Oracle function

I wrote a this function to return varchar2 from some tables.
create or replace function info_raum(in_name varchar2)
return varchar2
is
v_fi_name fitnesscenter.name%type;
v_num number;
v_output varchar2(2000) :='';
begin
for rec in (select * from raum where name = in_name)
loop
select name
into v_fi_name
from fitnesscenter
where fitnesscenternr = rec.fitnesscenternr;
select count(*)
into v_num
from ist_im
where raumnr = rec.raumnr;
v_output := v_output || 'Fitnesscenter: ' || v_fi_name || ' - GeräteAnz: ' || v_num || ' ---';
end loop;
return v_output;
end;
Wenn I execute the code I get this error:
Connecting to the database developer1.
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 7
Process exited.
Disconnecting from the database developer1.
I think this is because I need a bigger datatype for v_output. But I can not fix it.
You just need to use the max size of PL/SQL VARCHAR2 as it is may be exceeding the size of 2000.
use the following:
V_OUTPUT VARCHAR2(32767) := ''; -- also assignment to null is not needed here

Pass a table name and time stamp variable to a PL/SQL

I am writing a below PL/SQL code in SQL developer to delete data from a table with a timestamp column in the where condition. How can I modify this code to pass the table name and the timestamp value to values that I want based on what table and time records I want to delete the data from and create a stored procedure that can be reused.
DBMS_OUTPUT.ENABLE;
DECLARE
counter INTEGER := 0;
stop INTEGER;
BEGIN
dbms_output.put_line('START');
LOOP
counter := counter + 1;
DELETE my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM'
AND ROWNUM <= 100000;
SELECT COUNT(*)
INTO stop
FROM my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM';
EXIT WHEN stop <= 0;
COMMIT;
END LOOP;
dbms_output.put_line('Counter: ' || counter);
dbms_output.put_line('Left: ' || stop);
COMMIT;
END;
Adapting your anonymous to a stored procedure will, as indicated, require converting it to dynamic SQL. Always more difficult. And subject to SQL injection. For this you should validate string replacement parameters. I have a couple other changes:
Pass the desired as a timestamp, not a string, this allows/forces the
calling routine to determine the format and necessary conversion, if
any.
Added a parameter for column name as well. This frees naming columns
from the requirement of the procedure.
There is no need to count remaining items. Your loop processes until
that value reaches 0, but this can be determined by the number of
rows deleted on the last pass. Delete sets sql%rowcount to the number
of rows deleted. When the pass deletes 0 rows the process is
complete.
Removed the results display and the commit from the procedure, again
offloading this to the caller.
create or replace
procedure delete_values_by_timestamp
( p_table_name in varchar2
, p_column_name in varchar2
, p_timestamp in timestamp
, p_result_msg out varchar2
)
IS
table_name_parameter_invalid exception;
pragma exception_init(table_name_parameter_invalid, -44002);
column_name_parameter_invalid exception;
pragma exception_init(column_name_parameter_invalid, -44003);
k_nl constant varchar2(1) := chr(10);
k_max_delete_per_interation constant integer := 100000;
k_base_delete varchar2(256) :=
'delete from <table_name>' ||
' where <column_name> <= :1' ||
' and rownum <= :2';
v_delete_sql varchar2 (256) ;
v_rows_deleted integer := 0;
begin
v_delete_sql := replace(replace(k_base_delete,'<table_name>', dbms_assert.sql_object_name(p_table_name))
,'<column_name>',dbms_assert.simple_sql_name(p_column_name));
dbms_output.put_line('Running SQL:' || k_nl || v_delete_sql);
loop
execute immediate v_delete_sql using p_timestamp, k_max_delete_per_interation;
exit when sql%rowcount = 0;
v_rows_deleted :=v_rows_deleted + sql%rowcount;
end loop;
if v_rows_deleted = 0
then
p_result_msg := 'No Data Found';
else
p_result_msg := 'Number of Rows Deleted ' || to_char(v_rows_deleted);
end if;
exception
when table_name_parameter_invalid then
raise_application_error(-20199,'Invalid Table Name (' || p_table_name || ') specified.');
when column_name_parameter_invalid then
raise_application_error(-20198,'Invalid Column Name (' || p_column_name || ') specified.');
end delete_values_by_timestamp;
See example: In the example I reduce the number of rows deleted on each iteration from 100000 to 20. An additionally enhancement would be to pass the number of rows for each iteration as a parameter.
I couldn't test it but you could create a function whcih takes the table name and the timestamp as parameter.
As long you want to delete every record with the given timestamp you don't need to loop for each record.
This function should be just an example.
FUNCTION delete_values_by_timestamp (p_table_name IN VARCHAR2 DEFAULT NULL,
p_timestamp IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2
IS
v_count NUMBER := 0;
v_query VARCHAR2 (500) := '';
BEGIN
IF p_table_name IS NOT NULL
THEN
IF p_timestamp IS NOT NULL
THEN
v_query := 'SELECT COUNT(*)
FROM my_schema.' || p_table_name | '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query INTO v_count;
IF v_count > 0
THEN
v_query := 'DELETE FROM my_schema.' || p_table_name || '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query;
ELSE
RETURN 'NO RECORDS FOUND!';
END IF;
ELSE
RETURN 'TIMESTAMP EMPTY!';
END IF;
ELSE
RETURN 'TABLE NAME EMPTY!';
END IF;
END;

Dynamic typing or generics in Oracle PL/SQL

For some reason, I have certain fields in a table, that are collections of chars. Chars of different length. Example:
create or replace type t_charray_1 as varray(5) of char(1);
create or replace type t_charray_2 as varray(5) of char(2);
create or replace type t_charray_3 as varray(5) of char(3);
create or replace type t_charray_4 as varray(5) of char(4);
create table mytable (
field1 number,
field2 t_charray_1,
field3 t_charray_3,
Also, I have a function that returns a (fixed length) string representation of a mytable record. This function calls other functions that are returning the string representation of a given collection-typed field. Examples:
function to_chr(
p_array in t_charray_1,
pad_length in number,
p_list_length in number
) return char as
v_res varchar2(255) := '';
begin
for i in 1 .. p_list_length loop
if p_array is not null and p_array.exists(i) and p_array(i) is not null then
v_res := v_res || rpad(p_array(i), pad_length, ' ');
else
v_res := v_res || rpad(' ', pad_length, ' ');
end if;
end loop;
return v_res;
end to_chr;
------------------------------------------------------------------------------
function to_chr(
p_array in t_charray_2,
pad_length in number,
p_list_length in number
) return char as
v_res varchar2(255) := '';
begin
for i in 1 .. p_list_length loop
if p_array is not null and p_array.exists(i) and p_array(i) is not null then
v_res := v_res || rpad(p_array(i), pad_length, ' ');
else
v_res := v_res || rpad(' ', pad_length, ' ');
end if;
end loop;
return v_res;
end to_chr;
Note that these functions are overloaded versions of each other. The only difference in their signature is the type of the p_array argument.
Please also note that the bodies of these functions are identical.
Motivation
I want to eliminate duplicate code. What are my choices?
EDIT I have heard of sys.anydata but never used it. Can it be a solution?
You could write a procedure that takes the largest type, and explicitly CAST the smaller types to the larger type before passing them. Note that CAST can only be used in SQL
DECLARE
x t_charray_1 := t_charray_1();
y t_charray_2 := t_charray_2();
PROCEDURE foo( p_foo t_charray_2 )
AS
BEGIN
FOR i IN p_foo.FIRST..p_foo.LAST loop
dbms_output.put_line( p_foo(i) );
END LOOP;
END;
BEGIN
x.EXTEND;
x.EXTEND;
x(1) := 'A';
x(2) := 'B';
y.EXTEND;
y.EXTEND;
y(1) := 'AA';
y(2) := 'BB';
foo(y);
SELECT CAST(x AS t_charray_2) INTO y FROM dual;
foo(y);
END;
/
Try:
create or replace function to_chr(p_array in anydata,
pad_length in number,
p_list_length in number) return char as
v_res varchar2(255) := '';
x number;
v_array t_charray_4;
v_array1 t_charray_1;
v_array2 t_charray_2;
v_array3 t_charray_3;
begin
dbms_output.put_line(p_array.GetTypeName);
case p_array.GetTypeName
when '<schema>.T_CHARRAY_1' then
x := p_array.GetCollection(v_array1);
select cast(v_array1 as t_charray_4) into v_array from dual;
when '<schema>.T_CHARRAY_2' then
x := p_array.GetCollection(v_array2);
select cast(v_array2 as t_charray_4) into v_array from dual;
when '<schema>.T_CHARRAY_3' then
x := p_array.GetCollection(v_array3);
select cast(v_array3 as t_charray_4) into v_array from dual;
when '<schema>.T_CHARRAY_4' then
x := p_array.GetCollection(v_array);
end case;
for i in 1 .. p_list_length loop
if v_array is not null and v_array.exists(i) and v_array(i) is not null then
v_res := v_res || rpad(v_array(i), pad_length, ' ');
else
v_res := v_res || rpad(' ', pad_length, ' ');
end if;
end loop;
return v_res;
end to_chr;
you can run it like this:
declare
p_array anydata;
v_array t_charray_3 := new t_charray_3('aaa', 'bbb');
v_res varchar2(255);
begin
p_array := anydata.convertcollection(v_array);
v_res := to_chr(p_array => p_array, pad_length => 2, p_list_length => 3);
end;

Concatenation of CLOB datatypes in a LOOP in PL/SQL

I am trying to concatenate clobs in a PL/SQL loop and it has been returning null whilst when using DBMS_OUTPUT prints out the loop values and when executing each result of the clobs gives an output as well.
The system is meant to execute an already stored SQL in a table based on the report name passed into it. This particular report has many report names; hence the concatenation of each of the reports. The arguments passed are the report name, version of the report you're interested in, the kind of separator you want, and an argument list for the unknowns in the SQL if any. There are also two main types of SQL; 1 that needs the table_name be replaced with a temp table_name and another that needs an ID be appended to a table_name in the SQL.
please find below the code for the REPREF1 function.
CREATE OR REPLACE FUNCTION REPREF1(P_VER IN VARCHAR2 DEFAULT 'LATEST',
P_SEPARATOR IN VARCHAR2 DEFAULT ', ',
P_ARGLIST IN VAR DEFAULT NULL) RETURN CLOB IS
L_CLOB CLOB;
FUNCTION GET_CLOB(P_REPNAM IN VARCHAR2,
P_VER IN VARCHAR2 DEFAULT 'LATEST',
P_SEPARATOR IN VARCHAR2 DEFAULT ', ',
P_ARGLIST IN VAR DEFAULT NULL) RETURN CLOB IS
---------------------------------------------------------------------------------
-- TITLE - GET_CLOB beta - b.0 DATE 2010Mar12
--
-- DESCRIPTION - A function that return a report based on the report name put in
--
-- USAGE - select get_clob(p_repnam,p_ver, p_separator, var(varay(val_1,...val_n), varay(val_1,...val_n))) FROM dual
-----------------------------------------------------------------------------------------------------------------------------
V_SQL VARCHAR2(32767);
L_RESULT CLOB;
V_TITLE VARCHAR2(4000);
V_REPDATE VARCHAR2(30);
V_CNT NUMBER(2);
V_NUMARG NUMBER(3);
V_CDCRU NUMBER(3);
V_BCNT NUMBER(3);
V_NEWTABDAT VARCHAR2(30);
V_NEWTABLIN VARCHAR2(30);
L_COLLIST VARAY;
V_VER VARCHAR2(6);
N PLS_INTEGER;
V_CNTTAB NUMBER(3);
-- EXEC_SQL_CLOB
FUNCTION EXEC_SQL_CLOB(P_SQL IN VARCHAR2,
P_NUMARG IN NUMBER,
P_COLLIST IN VARAY DEFAULT NULL,
P_ARGLIST IN VARAY DEFAULT NULL,
P_SEPARATOR IN VARCHAR2 DEFAULT '') RETURN CLOB IS
------------------------------------------------------------------------------------------------------
-- TITLE - EXEC_SQL_CLOB beta - b.0 DATE 2010Mar22
--
-- DESCRIPTION - A function that returns a clob value after executing the sql query that is passed into it
--
-- USAGE - select exec_sql_clob(p_sql, p_numarg, var(varay(val_1, val_2,...val_n), varay(val_1, val_2,...val_n))) FROM dual
---------------------------------------------------------------------------------------------------------------
L_CUR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR;
L_STATUS INTEGER;
V_COL VARCHAR2(4000);
L_RESULT CLOB;
L_COLCNT NUMBER DEFAULT 0;
L_SEPARATOR VARCHAR2(10) DEFAULT '';
V_NUMARG NUMBER(3);
BEGIN
-- parse the query for the report
DBMS_SQL.PARSE(L_CUR, P_SQL, DBMS_SQL.NATIVE);
-- whilst it is not more than 255 per line
FOR I IN 1 .. 255
LOOP
BEGIN
-- define each column in the select list
DBMS_SQL.DEFINE_COLUMN(L_CUR, I, V_COL, 2000);
L_COLCNT := I;
EXCEPTION
WHEN OTHERS THEN
IF (SQLCODE = -1007) THEN
EXIT;
ELSE
RAISE;
END IF;
END;
END LOOP;
-- If query has no bind variables
IF (P_ARGLIST IS NULL) THEN
IF (P_NUMARG = 0) THEN
-- Execute the query in the cursor
L_STATUS := DBMS_SQL.EXECUTE(L_CUR);
LOOP
-- Exit loop when fetch is complete
EXIT WHEN(DBMS_SQL.FETCH_ROWS(L_CUR) <= 0);
L_SEPARATOR := '';
FOR I IN 1 .. L_COLCNT
LOOP
DBMS_SQL.COLUMN_VALUE(L_CUR, I, V_COL);
L_RESULT := L_RESULT || L_SEPARATOR || V_COL;
L_RESULT := REPLACE(REPLACE(L_RESULT, CHR(13) || CHR(10), ' '), CHR(10), ' ');
L_SEPARATOR := P_SEPARATOR;
END LOOP;
L_RESULT := L_RESULT || CHR(13);
END LOOP;
ELSE
RAISE_APPLICATION_ERROR(-20011, ' INCORRECT NUMBER OF ARGUMENTS PASSED IN LIST ');
END IF;
-- Query has bind variables
ELSE
-- Check if the numarg passed is the same has stored in the table
SELECT NUMARG
INTO V_NUMARG
FROM REPVER
WHERE REPCODE = P_SQL;
-- If number of arguments is greater than 0
IF (V_NUMARG > 0) THEN
-- Check if the number of arguments are the same
IF (P_NUMARG = V_NUMARG) THEN
-- Replace the bind variables in the query
FOR J IN 1 .. P_ARGLIST.COUNT
LOOP
DBMS_SQL.BIND_VARIABLE(L_CUR, P_COLLIST(J), P_ARGLIST(J));
END LOOP;
-- Execute the query in the cursor
L_STATUS := DBMS_SQL.EXECUTE(L_CUR);
LOOP
-- Exit loop when fetch is complete
EXIT WHEN(DBMS_SQL.FETCH_ROWS(L_CUR) <= 0);
L_SEPARATOR := '';
FOR I IN 1 .. L_COLCNT
LOOP
DBMS_SQL.COLUMN_VALUE(L_CUR, I, V_COL);
L_RESULT := L_RESULT || L_SEPARATOR || V_COL;
L_RESULT := REPLACE(REPLACE(L_RESULT, CHR(13) || CHR(10), ' '), CHR(10), ' ');
L_SEPARATOR := P_SEPARATOR;
END LOOP;
L_RESULT := L_RESULT || CHR(13);
END LOOP;
ELSE
RAISE_APPLICATION_ERROR(-20011, ' INCORRECT NUMBER OF ARGUMENTS PASSED IN LIST ');
END IF;
ELSE
-- If the number of argument is equal to 0
IF (P_NUMARG = 0) THEN
-- Execute the query in the cursor
L_STATUS := DBMS_SQL.EXECUTE(L_CUR);
LOOP
-- Exit loop when fetch is complete
EXIT WHEN(DBMS_SQL.FETCH_ROWS(L_CUR) <= 0);
L_SEPARATOR := '';
FOR I IN 1 .. L_COLCNT
LOOP
DBMS_SQL.COLUMN_VALUE(L_CUR, I, V_COL);
L_RESULT := L_RESULT || L_SEPARATOR || V_COL;
L_RESULT := REPLACE(REPLACE(L_RESULT, CHR(13) || CHR(10), ' '), CHR(10), ' ');
L_SEPARATOR := P_SEPARATOR;
END LOOP;
L_RESULT := L_RESULT || CHR(13);
END LOOP;
ELSE
RAISE_APPLICATION_ERROR(-20011, ' INCORRECT NUMBER OF ARGUMENTS PASSED IN LIST ');
END IF;
END IF;
END IF;
-- Close cursor
DBMS_SQL.CLOSE_CURSOR(L_CUR);
RETURN L_RESULT;
END EXEC_SQL_CLOB;
BEGIN
-- Check if the version entered is null or latest
IF (P_VER IS NULL)
OR (UPPER(P_VER) = UPPER('LATEST')) THEN
SELECT MAX(VER)
INTO V_VER
FROM REPORT B, REPVER R
WHERE UPPER(REPNAM) = UPPER(P_REPNAM)
AND B.REPREF = R.REPREF;
ELSE
V_VER := P_VER;
END IF;
-- Check if the repname and version entered exists
SELECT COUNT(*)
INTO V_CNT
FROM REPORT B, REPVER R
WHERE UPPER(REPNAM) = UPPER(P_REPNAM)
AND VER = V_VER
AND B.REPREF = R.REPREF;
IF (V_CNT > 0) THEN
-- Store the SQL statement, title and number of arguments of the report name passed.
SELECT REPCODE, REPTITLE, NUMARG, COLLIST
INTO V_SQL, V_TITLE, V_NUMARG, L_COLLIST
FROM REPVER R, REPORT B
WHERE UPPER(REPNAM) = UPPER(P_REPNAM)
AND B.REPREF = R.REPREF
AND VER = V_VER;
V_REPDATE := TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI');
L_RESULT := V_TITLE || ' (' || P_REPNAM || ' version ' || V_VER || ') generated ' || V_REPDATE || CHR(13) || CHR(13);
-- Check for some specific type of queries
SELECT COUNT(*)
INTO V_CDCRU
FROM REPVER R, REPORT B
WHERE CTDDATA = 'Y'
AND UPPER(REPNAM) = UPPER(P_REPNAM)
AND B.REPREF = R.REPREF
AND VER = V_VER;
SELECT COUNT(*)
INTO V_BCNT
FROM REPVER R, BODCREPS B
WHERE BENLIST = 'Y'
AND UPPER(REPNAM) = UPPER(P_REPNAM)
AND B.REPREF = R.REPREF
AND VER = V_VER;
IF (V_CDCRU > 0) THEN
V_NEWTABDATA := 'CT_' || 'DAT_' || P_ARGLIST(1) (P_ARGLIST(1).FIRST);
V_NEWTABLINK := 'CT_' || 'LIN_' || P_ARGLIST(1) (P_ARGLIST(1).FIRST);
-- Check if the tables exist
SELECT COUNT(*)
INTO V_CNTTAB
FROM ALL_TABLES
WHERE TABLE_NAME = V_NEWTABDAT
OR TABLE_NAME = V_NEWTABLIN
AND OWNER = 'SCOTT';
IF (V_CNTTAB > 0) THEN
V_SQL := UPPER(V_SQL);
V_SQL := REPLACE(V_SQL, 'CT_DAT_CRU', V_NEWTABDAT);
V_SQL := REPLACE(V_SQL, 'CT_LIN_CRU', V_NEWTABLIN);
ELSE
V_SQL := 'SELECT ''THE TABLE NOT CREATED YET''
FROM DUAL';
END IF;
END IF;
IF (V_BCNT > 0) THEN
V_SQL := UPPER(V_SQL);
V_SQL := REPLACE(V_SQL, 'LIST', P_ARGLIST(1) (P_ARGLIST(1).LAST));
END IF;
IF (P_ARGLIST IS NULL) THEN
-- execute the query
L_RESULT := L_RESULT || EXEC_SQL_CLOB(V_SQL, V_NUMARG, L_COLLIST, NULL, P_SEPARATOR);
ELSE
N := P_ARGLIST.COUNT;
-- execute the query
L_RESULT := L_RESULT || EXEC_SQL_CLOB(V_SQL, V_NUMARG, L_COLLIST, P_ARGLIST(N), P_SEPARATOR);
END IF;
RETURN L_RESULT;
ELSE
RAISE_APPLICATION_ERROR(-20012, P_REPNAM || ' or ' || P_VER || ' DOES NOT EXIST ');
END IF;
END GET_CLOB;
BEGIN
FOR I IN (SELECT REPNAM
FROM REPORT
WHERE REPREF NOT IN ('R01', 'R02', 'R03', 'R04'))
LOOP
SELECT CONCAT_CLOB(GET_CLOB(I.REPNAM, P_VER, P_SEPARATOR, P_ARGLIST))
INTO L_CLOB
FROM DUAL;
DBMS_OUTPUT.PUT_LINE(I.REPNAM);
-- DBMS_OUTPUT.PUT_LINE (COUNT(i.REPNAM));
END LOOP;
RETURN L_CLOB;
END REPREF1;
/
Cheers,
Tunde
Many thanks APC for making the code look better.
#Robert, the last loop in the code returns null even with the CONCAT_CLOB aggregate function that concatenates clobs.
FOR I IN (SELECT REPNAM
FROM REPORT
WHERE REPREF NOT IN ('R01', 'R02', 'R03', 'R04'))
LOOP
SELECT CONCAT_CLOB(GET_CLOB(I.REPNAM, P_VER, P_SEPARATOR, P_ARGLIST))
INTO L_CLOB
FROM DUAL;
DBMS_OUTPUT.PUT_LINE(I.REPNAM);
END LOOP;
when I try this,
FOR I IN (SELECT REPNAM
FROM REPORT
WHERE REPREF NOT IN ('R01', 'R02', 'R03', 'R04'))
LOOP
L_CLOB := L_CLOB || CHR(13) || GET_CLOB(I.REPNAM, P_VER, P_SEPARATOR, P_ARGLIST);
DBMS_OUTPUT.PUT_LINE(I.REPNAM);
END LOOP;
It also gives null; but this time the dbms output for the repnam are not complete.
Don't know about your code. Here is how it works for me:
Whenever I create a function returning a clob value I do this:
function foo return clob is
l_clob clob;
begin
dbms_lob.createtemporary(lob_loc => l_clob, cache => true, dur => dbms_lob.call);
...
return l_clob;
end;
When concatenating values into a clob I use a function:
procedure add_string_to_clob(p_lob in out nocopy clob
,p_string varchar2) is
begin
dbms_lob.writeappend(lob_loc => p_lob, amount => length(p_string), buffer => p_string);
end;
You have to use
dbms_lob.substr(your clob parameter,start position, length)
e.g
dbms_output('my clob value:' || dbms_lob.substr(your clob parameter,start position, length);
But you can print in a string max 4000 character, you can then use this in a looping function to print 4000 characters in each line.

Resources