I am learning plsql and I have some doubts.
How do I get the size of all substrings in the string? The way I did it, I'm only managing to return the size of just the first substring.
set serveroutput on;
create or replace procedure pr_size (value varchar2)
as
answer varchar2 (300): = '';
begin
for x in 1 .. length (value) loop
cont: = x;
if substr (value, x, 1) = ''
then dbms_output.put_line ('Size:' || length (answer));
exit;
else answer: = answer || substr (value, x, 1);
end if;
end loop;
end;
call pr_size ('Word size calculation test');
you can do something like this
DECLARE
type string_table is table of VARCHAR2(100);
st string_table;
BEGIN
SELECT regexp_substr('THIS IS TEST', '[^ ]+', 1, LEVEL) BULK COLLECT INTO st FROM dual CONNECT by level <= regexp_count('THIS IS TEST', '[^ ]+');
for i in 1..st.COUNT
LOOP
dbms_output.put_line(length(st(i)));
END LOOP;
END;
If you want a string of length like in your code then
CREATE OR REPLACE PROCEDURE pr_size (value varchar2)
AS
type string_table is table of VARCHAR2(100);
st string_table;
answer VARCHAR2(100);
BEGIN
SELECT regexp_substr(value, '[^ ]+', 1, LEVEL) BULK COLLECT INTO st FROM dual CONNECT by level <= regexp_count(value, '[^ ]+');
for i in 1..st.COUNT
LOOP
answer := length(st(i))||' '||answer;
END LOOP;
dbms_output.put_line(answer);
END;
If you want to use your logic then I have corrected your logic
DECLARE
value VARCHAR2(100) := 'this is test for word length';
answer VARCHAR2(100);
cont PLS_INTEGER := 0;
BEGIN
for x in 1 .. length (value) loop
if substr (value, x, 1) = ' ' then
dbms_output.put_line ('Size:' || cont);
cont := 0;
ELSE
cont := cont + 1;
end if;
end loop;
dbms_output.put_line ('Size:' || cont);
END;
I am attempting to compile a package body to test a procedure in the package and I keep getting the above error.
CREATE TABLE TempBicycle AS
SELECT * FROM bike_shop.bicycle;
CREATE OR REPLACE PACKAGE BIKESHOP AS
PROCEDURE EXTRACT_BICYCLES (output_type IN VARCHAR2);
PROCEDURE EXTRACT_CUSTOMERS;
FUNCTION CUSTOMER_BIKES RETURN BOOLEAN;
PROCEDURE ARCHIVE_CUSTOMER_BIKES;
count NUMBER(38,0);
CURSOR ext_bikes_cur IS
SELECT SerialNumber, ModelType, PaintID, FrameSize, OrderDate, StartDate, ShipDate, Construction, ListPrice,
SalePrice, SalesTax, SaleState
FROM TempBicycle
ORDER BY OrderDate ASC;
END BIKESHOP;
/
CREATE OR REPLACE PACKAGE BODY BIKESHOP AS
PROCEDURE EXTRACT_BICYCLES (output_type IN VARCHAR2) IS
BEGIN
IF output_type = 'D' THEN
count := 0;
FOR Bikes IN ext_bikes_cur LOOP
INSERT INTO bicycles
( SerialNumber, ModelType, PaintID, FrameSize, OrderDate, StartDate, ShipDate, Construction, ListPrice,
SalePrice, SalesTax, SaleState)
VALUES ( Bikes.SerialNumber, Bikes.ModelType, Bikes.PaintID, Bikes.FrameSize, Bikes.OrderDate, Bikes.StartDate,
Bikes.ShipDate, Bikes.Construction, Bikes.ListPrice, Bikes.SalePrice, Bikes.SalesTax, Bikes.SaleState);
count := count +1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Records Inputted: ' || count);
ELSE IF output_type = 'S' THEN
FOR Bikes IN ext_bikes_cur LOOP
DBMS_OUTPUT.PUT_LINE(chr(10) || '----------Bike Information----------');
DBMS_OUTPUT.PUT_LINE ('Serial Number: ' || Bikes.SerialNumber);
DBMS_OUTPUT.PUT_LINE ('Model: ' || Bikes.ModelType);
DBMS_OUTPUT.PUT_LINE ('Paint ID: ' || Bikes.PaintID);
DBMS_OUTPUT.PUT_LINE ('Frame: ' || Bikes.FrameSize);
DBMS_OUTPUT.PUT_LINE ('Date Ordered: ' || Bikes.OrderDate);
DBMS_OUTPUT.PUT_LINE ('Start Date: ' || Bikes.StartDate);
DBMS_OUTPUT.PUT_LINE ('Date Shipped: ' || Bikes.ShipDate);
DBMS_OUTPUT.PUT_LINE ('Construction: ' || Bikes.Construction);
DBMS_OUTPUT.PUT_LINE ('Listed Price: ' || Bikes.ListPrice);
DBMS_OUTPUT.PUT_LINE ('Sale Price: ' || Bikes.SalePrice);
DBMS_OUTPUT.PUT_LINE ('Sales Tax: ' || Bikes.SalesTax);
DBMS_OUTPUT.PUT_LINE ('State Sold: ' || Bikes.SaleState);
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Incorrect Input');
END IF;
END;
PROCEDURE EXTRACT_CUSTOMERS IS
BEGIN
NULL;
END;
FUNCTION CUSTOMER_BIKES RETURN BOOLEAN IS
BEGIN
RETURN TRUE;
END;
PROCEDURE ARCHIVE_CUSTOMER_BIKES IS
BEGIN
NULL;
END;
END BIKESHOP;
/
BEGIN
BikeShop.ExtractBicyclesaz('S');
END
I am wanting the procedure to print out to the console the contents of the cursor if the procedure is passed an "S" and for it to input the cursor data if it is passed a "D"
Error(37,6): PLS-00103: Encountered the symbol ";" when expecting one of the following: if
PL/SQL uses ELSIF, not ELSE IF. Correct that in EXTRACT_BICYCLES and you should be good.
Well, actually ELSE IF is allowed, but it changes the structure of the statements. For example, what you're trying to do is
IF something THEN
ya_da;
ELSIF something_else THEN
ya_da_ya_da;
ELSE
the_other_thing;
END IF;
If you really wanted to use ELSE IF the code structure would become
IF something THEN
ya_da;
ELSE
IF something_else THEN
ya_da_ya_da;
ELSE
the_other_thing;
END IF;
END IF;
So you end up needing an END IF for the "outer" IF statement, and a second END IF for the "inner" IF statement.
I am taking the emp3 table which is same as emp table.
DECLARE
CURSOR incr_cur IS SELECT * FROM emp3 FOR UPDATE OF sal;
v_job emp3.job%TYPE := '&ENTER_Job';
v_cnt INTEGER;
BEGIN
FOR r_l IN incr_cur LOOP
IF v_job = r_l.job THEN
UPDATE emp3 SET sal = sal + 100 WHERE CURRENT OF incr_cur;
END IF;
END LOOP;
FOR p_l IN incr_cur LOOP
IF v_job = p_l.job THEN
DBMS_OUTPUT.PUT_LINE('The Salary of ' || p_l.ename || ' is: ' || p_l.sal || ' (Incremented).');
ELSE
DBMS_OUTPUT.PUT_LINE('The Salary of ' || p_l.ename || ' is: ' || p_l.sal || ' (Not Incremented).');
END IF;
END LOOP;
END;
After executing the script it will ask for user input.
I gave the INPUT 'CLERK' and the OUTPUT,
But I want output like this,
Just increment a variable after the if condition and then display it at the end.
DECLARE
CURSOR ..
..
v_cnt INTEGER;
BEGIN
..
..
FOR p_l in incr_cur --second for loop
LOOP
IF v_job = p_l.job
v_cnt := v_cnt + 1;
..
END LOOP;
DBMS_OUTPUT.PUT_LINE('The Salary of '||v_cnt||' Employees are Incremented by 100');
END;
DECLARE
CURSOR incr_cur IS SELECT * FROM emp3 FOR UPDATE OF sal;
v_job emp3.job%TYPE := '&ENTER_Job';
v_cnt INTEGER := 0;
BEGIN
FOR r_l IN incr_cur LOOP
IF v_job = r_l.job THEN
UPDATE emp3 SET sal = sal + 100 WHERE CURRENT OF incr_cur;
END IF;
END LOOP;
FOR p_l IN incr_cur LOOP
IF v_job = p_l.job THEN
v_cnt := v_cnt + 1;
DBMS_OUTPUT.PUT_LINE('The Salary of ' || p_l.ename || ' is: ' || p_l.sal || ' (Incremented).');
ELSE
DBMS_OUTPUT.PUT_LINE('The Salary of ' || p_l.ename || ' is: ' || p_l.sal || ' (Not Incremented).');
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE('The Salary of '|| v_cnt ||' Employees are Incremented by 100');
END;
I have a value that i dont know exactly in which column it is inserted. I can determine that since this table columns are named as C1....C99. I am going to find the column using the following code. But when the no data found exception is called, I cant start my loop again.
DECLARE
i number:=1;
k boolean := true;
output number;
stmt varchar(500);
BEGIN
<<repeat>>
while(k)
loop
DBMS_OUTPUT.PUT_LINE( 'c column -->'||i );
EXECUTE IMMEDIATE 'select 1 from X_TAB t where t.c'||i||'= ''NOTE_NFE'''
into output;
IF output = 1 then
DBMS_OUTPUT.PUT_LINE( 'c column'||i );
k:=false;
END IF;
i:=i+1;
IF i = 100 then
k:=false;
END IF;
END LOOP;
EXCEPTION
when no_data_found then
i:=i+1;
if i = 100 then
k:=false;
end if;
goto repeat;
END;
/
I think that moving your try catch to inside the loop will do the trick for you.
DECLARE
i number:=1;
k boolean := true;
output number;
stmt varchar(500);
BEGIN
<<repeat>>
while(k)
loop
DBMS_OUTPUT.PUT_LINE( 'c column -->'||i );
begin
EXECUTE IMMEDIATE 'select 1 from X_TAB t where t.c'||i||'= ''FISCAL_NOTE_NFE''' into output;
exception when no_data_found then
output := 0; --set a default value
dbms_output.put_line('no data found.');
end;
IF output = 1 then
DBMS_OUTPUT.PUT_LINE( 'c column'||i );
k:=false;
END IF;
i:=i+1;
IF i = 100 then
k:=false;
END IF;
END LOOP;
END;
/
You can use:
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM X_TAB
WHERE dynamic_column_name = 'FISCAL_NOTE_NFE'
)
THEN 1
ELSE 0
END
FROM DUAL
It will never throw the exception as it will always return exactly one row.
You can use it like:
DECLARE
i INT := 0;
output INT;
BEGIN
FOR k IN 1 .. 100 LOOP
DBMS_OUTPUT.PUT_LINE( 'c column -->'||k );
EXECUTE IMMEDIATE 'SELECT CASE WHEN EXISTS(SELECT 1 FROM X_TAB WHERE c'||k||' = ''FISCAL_NOTE_NFE'') THEN 1 ELSE 0 END FROM DUAL'
INTO output;
IF output = 1 THEN
DBMS_OUTPUT.PUT_LINE( 'c column'||k );
i := k;
EXIT;
END IF;
END LOOP;
-- Do something with i
END;
/
You can also use
select count(1) from X_TAB
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.