I try to create plsql block but it doesnt work. Oracle says that i have error at line 2. I think it could be because substitution variable is not placed right !?
DECLARE
V_ENAME EMPLOYEES.LAST_NAME%TYPE := '&LNAME';
V_SAL EMPLOYEES.SALARY%TYPE;
BEGIN
SELECT LAST_NAME, SALARY
INTO V_ENAME, V_SAL
FROM employees WHERE LAST_NAME = V_ENAME;
IF V_SAL < 3000 THEN
v_sal := v_sal + 500;
DBMS_OUTPUT.PUT_LINE (v_ename || 'have increasement ');
ELSIF V_SAL > 3000 THEN
DBMS_OUTPUT.PUT_LINE (v_ename || 'do not have increasement ');
ELSE
DBMS_OUTPUT.PUT_LINE ('error');
END IF;
END;
Since there can be many employees with the last name passed by the user, you may use an implicit CURSOR FOR LOOP. Also, add first_name in the output for clarity.
DECLARE
v_ename employees.last_name%TYPE := '&LNAME';
v_sal employees.salary%TYPE;
BEGIN
for rec IN ( SELECT first_name,last_name,salary
FROM employees WHERE last_name = v_ename
)
LOOP
IF rec.salary < 3000 THEN
v_sal := rec.salary + 500;
dbms_output.put_line (rec.first_name||' '||rec.last_name ||
' has an increase');
ELSIF rec.salary > 3000 THEN
dbms_output.put_line (rec.first_name||' '||rec.last_name ||
' does not have an increase ');
ELSE dbms_output.put_line ('error');
END IF;
END LOOP;
END;
/
Execution
..
old:DECLARE
v_ename employees.last_name%TYPE := '&LNAME';
..
new:DECLARE
v_ename employees.last_name%TYPE := 'Grant';
..
Douglas Grant has an increase
Kimberely Grant does not have an increase
PL/SQL procedure successfully completed.
Not sure if it's your problem but there is really no need to select last_name into v_ename when you are already ensuring last_name is equal to v_ename in the where clause.
Related
DECLARE
v_id NUMBER := 200;
v_fname VARCHAR2(20);
v_lname VARCHAR2(20);
v_sal NUMBER; BEGIN
SELECT first_name, last_name, salary
INTO v_fname, v_lname, v_sal
FROM STAFF
WHERE id=v_id;
DBMS_OUTPUT.PUT_LINE(v_fname||' '||v_fname||' makes '||v_sal); END; /
Saw this code in a StackOverflow post. Wondering how do I print on the screen a message only in case the salary of the selected record is higher than 5000 pounds?
What would be the PL/SQL for that and where do I put it in the exi?
I am learning Oracle for a week now and trying to go through the documentation as much as I can. But having a hard time understanding everything.
Thanks in Advance
Simply this:
DECLARE
v_id NUMBER := 200;
v_fname VARCHAR2(20);
v_lname VARCHAR2(20);
v_sal NUMBER;
BEGIN
SELECT first_name, last_name, salary
INTO v_fname, v_lname, v_sal
FROM STAFF
WHERE id=v_id;
IF v_sal > 5000 THEN
DBMS_OUTPUT.PUT_LINE(v_fname||' '||v_fname||' makes '||v_sal);
END IF;
END;
/
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 tried to fix this for two days and I couldnt.
I know why the code happens but Im not sure where.
or why its happening...
This has to be done in PLSQL
its a homework assignment.
SET SERVEROUTPUT ON
DECLARE
V_IDNO PAYDATA1.IDNO%TYPE;
V_NAME PAYDATA1.NAME%TYPE;
V_SAL PAYDATA1.SALARY%TYPE;
V_JOB PAYDATA1.JOBCODE%TYPE;
V_PAY PAYDATA1.PAYHR%TYPE;
V_IDNO1 PAYTRAN1.IDNO%TYPE;
V_HOURSWK PAYTRAN1.HOURSWK%TYPE;
V_HOURS HOURSWKD.HOURSWK%TYPE;
V_CHECK NUMBER(10);
CURSOR paydata_cursor IS
SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR FROM PAYDATA1
ORDER BY IDNO;
CURSOR paytran_cursor IS
SELECT IDNO, HOURSWK FROM PAYTRAN1
WHERE V_IDNO = IDNO
order by IDNO;
BEGIN
OPEN paydata_cursor;
LOOP
FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY;
EXIT WHEN paydata_cursor%NOTFOUND;
IF V_SAL > 0 THEN
V_CHECK := V_SAL / 52;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
IF V_SAL = 0 AND V_HOURSWK < 41 THEN
V_CHECK := V_PAY * V_HOURS;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
ELSIF V_SAL = 0 AND V_HOURSWK > 40 THEN
V_CHECK := V_PAY * V_HOURS;
V_CHECK := V_SAL + ((V_HOURSWK * 1.5) * (V_HOURSWK - 40));
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
END LOOP;
CLOSE paydata_cursor;
END;
/
SET SERVEROUTPUT OFF
IM GETTING THIS ERROR, TRIED TO FIX IT ALL DAY AND COULDN’T. ANY ADVICE?
SQL> # CURSOR5
DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 22
I can see a few issues with your code but without knowing much more info it's difficult to diagnose...but I'll try:
It looks like you're selecting into the wrong variables when opening your cursor.
You also haven't opened your paytran_cursor anywhere. You can add that code yourself but until you do, your check of V_HOURSWK won't be very useful etc.
Try this instead:
SET SERVEROUTPUT ON
DECLARE
V_IDNO PAYDATA1.IDNO%TYPE;
V_NAME PAYDATA1.NAME%TYPE;
V_SAL PAYDATA1.SALARY%TYPE;
V_JOB PAYDATA1.JOBCODE%TYPE;
V_PAY PAYDATA1.PAYHR%TYPE;
V_IDNO1 PAYTRAN1.IDNO%TYPE;
V_HOURSWK PAYTRAN1.HOURSWK%TYPE;
V_HOURS HOURSWKD.HOURSWK%TYPE;
V_CHECK NUMBER(10);
CURSOR paydata_cursor IS
SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR
FROM PAYDATA1
ORDER BY IDNO;
CURSOR paytran_cursor IS
SELECT IDNO, HOURSWK
FROM PAYTRAN1
WHERE V_IDNO = IDNO
order by IDNO;
BEGIN
OPEN paydata_cursor;
LOOP
-- Changed the variables you were selecting into
FETCH paydata_cursor INTO V_IDNO, V_NAME, V_JOB, V_SAL, V_PAY;
EXIT WHEN paydata_cursor%NOTFOUND;
IF V_SAL > 0
THEN
V_CHECK := V_SAL / 52;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
IF V_SAL = 0 AND V_HOURSWK < 41
THEN
V_CHECK := V_PAY * V_HOURS;
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
ELSIF V_SAL = 0 AND V_HOURSWK > 40
THEN
V_CHECK := V_PAY * V_HOURS;
V_CHECK := V_SAL + ((V_HOURSWK * 1.5) * (V_HOURSWK - 40));
DBMS_OUTPUT.PUT_LINE(V_IDNO|| ' HAS A CHECK FOR: '||V_CHECK);
END IF;
END LOOP;
CLOSE paydata_cursor;
END;
/
SET SERVEROUTPUT OFF
Hope it helps.
EDIT:
I have tried to guess what you are trying to do with your code and think that this below might go some way to fixing your issues in a slightly more efficient manner:
SET SERVEROUTPUT ON
DECLARE
--
c_max_hours CONSTANT NUMBER := 40;
--
-- N.B.: I have assumed that there may be more than one entry per IDNO for
-- hours worked, if this is not the case then you can remove the SUM() and
-- the GROUP BY clause
--
CURSOR pay_cursor
IS
SELECT IDNO,
NAME,
JOBCODE,
SALARY,
PAYHR,
SUM(HOURSWK) AS HOURS_WORKED
FROM PAYDATA1
JOIN PAYTRAN1 USING (IDNO)
GROUP BY IDNO,
NAME,
JOBCODE,
SALARY,
PAYHR;
--
V_CHECK NUMBER;
pay_record pay_cursor%ROWTYPE;
--
BEGIN
-- Depending on the rows in your cursor you might want to increase the output buffer for DBMS_OUTPUT
DBMS_OUTPUT.ENABLE(1000000);
--
OPEN pay_cursor;
LOOP
-- Fetch the data into your cursor rowtype variable
FETCH paydata_cursor INTO pay_record;
EXIT WHEN pay_cursor%NOTFOUND;
--
-- ASSUMPTION: salary is not NULL (i.e. 0 or more).
--
IF pay_record.salary > 0
THEN
V_CHECK := pay_record.salary / 52;
ELSE
--
-- Salary must be zero
--
IF pay_record.hours_worked <= c_max_hours
THEN
V_CHECK := pay_record.payhr * pay_record.hours_worked;
ELSE
-- Must be > c_max_hours
V_CHECK := pay_record.payhr * pay_record.hours_worked;
V_CHECK := pay_record.salary + ((pay_record.hours_worked * 1.5) * (pay_record.hours_worked - 40));
END IF;
END IF;
--
-- Output your result
--
DBMS_OUTPUT.PUT_LINE(pay_record.idno|| ' HAS A CHECK FOR: '||V_CHECK);
END LOOP;
CLOSE paydata_cursor;
EXCEPTION
WHEN others
THEN
-- Close the cursor if it is still open
IF pay_cursor%ISOPEN
THEN
CLOSE pay_cursor;
END IF;
-- Re-raise the error
RAISE;
END;
/
SET SERVEROUTPUT OFF
I hope it's useful.
P.S. I couldn't check this in a real environment as I'm not at my usual PC so apologies for any syntax errors.
Problem is that your column paydata1.JOBCODE is not a number
and in this code FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY; you are assigning it to V_CHECK which is number
Change the order like this: FETCH paydata_cursor INTO V_IDNO, V_NAME, V_JOB, V_CHECK, V_PAY; and it should work but ensure that paydata1.salary is a number
Also i am not sure when you have declared V_SAL then why are you using V_CHECK in this cursor fetch.
at line 13 when you are defining your cursor paydata_cursor as columns like
SELECT IDNO, NAME, JOBCODE, SALARY, PAYHR FROM PAYDATA1
ORDER BY IDNO;
column sequence IDNO, NAME, JOBCODE, SALARY, PAYHR
but in line 23 i.e.
FETCH paydata_cursor INTO V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY;
you are actually fetching the columns like this
IDNO, NAME, JOBCODE, SALARY, PAYHR into
V_IDNO, V_NAME, V_CHECK, V_JOB, V_PAY
that means JOBCODE is going into V_CHECK
and SALARY is going into V_JOB
since salary must be number and v_check must be varchar
i think this is why u r getting this error
Thanks
Sid
I want to check my employee table if there is any employee who works as an
employee for exactly one year or two years, or three years, ...
The Problem for me now is that i dont know how i can check if a number is
an integer or not.
CREATE OR REPLACE PROCEDURE jubilar
IS
v_cur_date DATE := TO_DATE('03-JAN-2012');
v_cur_year NUMBER;
v_first_name employees.first_name%TYPE;
v_last_name employees.last_name%TYPE;
v_hire_date employees.hire_date%TYPE;
CURSOR c_emp_cursor IS
SELECT first_name, last_name, hire_date FROM employees;
BEGIN
OPEN c_emp_cursor;
LOOP
FETCH c_emp_cursor INTO v_first_name, v_last_name, v_hire_date;
EXIT WHEN c_emp_cursor%NOTFOUND;
v_cur_year := round((v_cur_date - v_hire_date) / 365, 1);
IF v_cur_year ???
DBMS_OUTPUT.PUT_LINE(v_first_name || ' ' || v_last_name || ' ist heute ' || v_cur_year || ' Jahre im Unternehmen tätig.');
END IF;
END LOOP;
CLOSE c_emp_cursor;
END jubilar;
/
At this line
IF v_cur_year ??
I need to check if v_cur_year is an integer or not. Because if it is the employee
works for exactly X year as an employee. And i need to know that.
EDIT:
I tried this:
CREATE OR REPLACE PROCEDURE jubilar
IS
v_cur_date DATE := TO_DATE('03/01/12', 'dd/mm/yy');
v_cur_year NUMBER;
v_cur_year_temp VARCHAR2(100);
v_first_name employees.first_name%TYPE;
v_last_name employees.last_name%TYPE;
v_hire_date employees.hire_date%TYPE;
CURSOR c_emp_cursor IS SELECT first_name, last_name, hire_date FROM employees;
BEGIN
OPEN c_emp_cursor;
LOOP
FETCH c_emp_cursor INTO v_first_name, v_last_name, v_hire_date;
EXIT WHEN c_emp_cursor%NOTFOUND;
v_cur_year := round((v_cur_date - v_hire_date) / 365, 1);
v_cur_year_temp := TO_CHAR(v_cur_year);
IF REGEXP_COUNT(v_cur_year_temp, ',') = 0 THEN
DBMS_OUTPUT.PUT_LINE(v_first_name || ' ' || v_last_name || ' ist heute ' || v_cur_year || ' Jahre im Unternehmen tätig.' || TO_CHAR(v_hire_date));
END IF;
END LOOP;
CLOSE c_emp_cursor;
END jubilar;
/
But it gives me wrong persons with hire_date for example 17/01/2005
I also tried this:
CREATE OR REPLACE PROCEDURE jubilar
IS
v_cur_date DATE := TO_DATE('03/01/12', 'dd/mm/yy');
v_cur_year NUMBER;
v_first_name employees.first_name%TYPE;
v_last_name employees.last_name%TYPE;
v_hire_date employees.hire_date%TYPE;
CURSOR c_emp_cursor IS SELECT first_name, last_name, hire_date FROM employees;
BEGIN
OPEN c_emp_cursor;
LOOP
FETCH c_emp_cursor INTO v_first_name, v_last_name, v_hire_date;
EXIT WHEN c_emp_cursor%NOTFOUND;
v_cur_year := round((v_cur_date - v_hire_date) / 365, 1);
IF trunc(v_cur_year) = v_cur_year THEN
DBMS_OUTPUT.PUT_LINE(v_first_name || ' ' || v_last_name || ' ist heute ' || v_cur_year || ' Jahre im Unternehmen tätig.' || TO_CHAR(v_hire_date));
END IF;
END LOOP;
CLOSE c_emp_cursor;
END jubilar;
/
But it gives me wrong persons with hire_date for example 17/01/2005
This may help you ..
DECLARE
d1 DATE := TO_DATE ('01/12/12', 'mm/dd/yy');
d2 DATE := SYSDATE;
n1 NUMBER;
chk VARCHAR2 (100);
BEGIN
n1 := ROUND ( (d2 - d1) / 365, 1);
DBMS_OUTPUT.put_line (n1);
chk := TO_CHAR (n1);
DBMS_OUTPUT.put_line (chk);
IF REGEXP_COUNT (chk, '.') != 0
THEN
---YOUR LOGIC
END IF;
END;
To check for employees who are employed exactly two years at e.g. January 14th, you can use this:
select *
from employees
where months_between(DATE '2014-01-14', trunc(hire_date)) / 12 = 2;
(I prefer using ANSI date literals over the to_date() function. Works on multiple DBMS and is less typing)
months_between(...) / 12 will result in a fractional value if it's not exactly one year and therefore the comparison with a non-fractional value will fail.
Just change the comparison date (DATE '2014-01-14') and the condition ( =2) to accommodate for other dates or durations.
SQLFiddle example: http://sqlfiddle.com/#!4/27c3d/4
I would do it like this:
with y as
(select trunc(ADD_MONTHS(SYSDATE, -12 * LEVEL)) as the_date, LEVEL as anniversary
from dual
connect by LEVEL <= 6)
select first_name, last_name, hire_date, anniversary, the_date
join y on the_date = hire_date
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.