invalid refernce to variable c sys refcursor - plsql

DECLARE
c SYS_REFCURSOR;
lv_emp emp%ROWTYPE;
BEGIN
OPEN c FOR SELECT employee_id FROM emp;
--fetch c into lv_emp;
DBMS_OUTPUT.put_line (c.emloyee_id);
END;
ERROR at line 7:
ORA-06550: line 7, column 24:
PLS-00487: Invalid reference to variable 'C'
ORA-06550: line 7, column 1:
Statement ignored

If the objective is to list all the employee_id, you could do with REFCURSOR as cited below in an anonymous block.
VARIABLE c REFCURSOR
DECLARE
BEGIN
OPEN :c FOR SELECT empno FROM scott.emp;
END;
/
PRINT c;
SYS_REFCURSOR in an anonymous block
DECLARE
c_cursor SYS_REFCURSOR;
l_row scott.emp%ROWTYPE;
BEGIN
OPEN c_cursor FOR SELECT * FROM scott.emp;
LOOP
FETCH c_cursor INTO l_row;
EXIT WHEN c_cursor%NOTFOUND;
DBMS_OUTPUT.put_line (l_row.empno || ' : ' || l_row.ename);
END LOOP;
CLOSE c_cursor;
END;
/
Using SYS_REFCURSOR in a Procedure
Procedure Creation
CREATE OR REPLACE PROCEDURE test_proc_cursor (c OUT SYS_REFCURSOR)
AS
BEGIN
OPEN c FOR SELECT empno FROM scott.emp;
END test_proc_cursor;
/
Execution of the above procedure
DECLARE
cur SYS_REFCURSOR;
p_empno VARCHAR2 (50);
BEGIN
test_proc_cursor (c => cur);
LOOP
FETCH cur INTO p_empno;
EXIT WHEN cur%NOTFOUND;
DBMS_OUTPUT.put_line ('empno -->' || p_empno);
END LOOP;
CLOSE cur;
END;
/

Related

PL/SQL: I get the error "Encountered the symbol "OPEN" when expecting one of the following: . ( * # % & - + / "

My code:
create table dep_emp_ast(
cod_dep number(3),
cod_ang number(3));
declare
type cref is ref cursor;
c cref;
type tab_imb is table of dept_ast.department_id%type;
t tab_imb:=tab_imb();
v_ang emp_ast.employee_id%type;
begin
select distinct department_id
bulk collect into t
from dept_ast;
forall i in 1..t.count
open c for select employee_id
from emp_ast
where department_id=t(i);
loop
fetch c into v_ang
insert into dep_emp_ast
values(t(i),v_ang);
exit when c%notfound;
end loop;
close c;
end;
/
My error says I cannot open a cursor there. But why? I want to re-open the cursor and re-use it for every value of t(i).
forall must be followed by a DML statement:
for example:
forall i in depts.first..depts.last
delete employees_temp
where department_id = depts(i);
I think what you wanted was something like:
declare
c sys_refcursor;
type tab_imb is table of dept_ast.department_id%type;
t tab_imb:=tab_imb();
v_ang emp_ast.employee_id%type;
begin
select distinct department_id
bulk collect into t
from dept_ast;
for i in 1..t.count loop
open c for
select employee_id
from emp_ast
where department_id=t(i);
loop
fetch c into v_ang;
insert into dep_emp_ast
values(t(i),v_ang);
exit when c%notfound;
end loop;
close c;
end loop;
end;
which can be simplified to
begin
for d in (
select distinct department_id
from dept_ast
)
loop
for e in (
select employee_id
from emp_ast
where department_id = d.department_id
)
loop
insert into dep_emp_ast
values (d.department_id, e.employee_id);
end loop;
end loop;
end;
which boils down to
insert into dep_emp_ast (cod_dep, cod_ang)
select e.department_id, e.employee_id
from emp_ast e
where e.department_id in
( select department_id
from dept_ast );

PL/SQL Calling a function to a procedure

Previously,I asked about creating a function that returns total amount of salaries from a parameter city.
I chose Dallas for instance.Tables are EMP and DEPT:
You can find them below
https://livesql.oracle.com/apex/livesql/file/content_O5AEB2HE08PYEPTGCFLZU9YCV.html
Mistakenly I wrote in my language instead of english at the end of it but I corrected it.
Now I need to create a procedure which lists ascending the employees and their salaries from another parameter city.After listing them I need to call the function for the second city.Problem is I get an error for the 'loop' from the procedure and i got no idea why.
set serveroutput on;
create or replace function show_sal (local dept.loc%type) return number as
vval number;
begin
select sum(emp.sal)
into vval
from emp inner join dept on dept.deptno = emp.deptno
where upper(dept.loc) = upper(local);
return vval;
end;
/
begin
dbms_output.put_line('Total sum of salaries from DALLAS = ' || show_sal('DALLAS'));
end;
/
-------------------------------------------------------------------------------------------------
CREATE OR REPLACE PROCEDURE show_employees(v_loc dept.loc%TYPE) AS
CURSOR c IS
SELECT ename,sal
FROM emp INNER JOIN dept ON emp.deptno = dept.deptno
WHERE UPPER(loc)=UPPER(v_loc)
ORDER BY ename ASC;
v_name VARCHAR2;
v_salaries emp.sal%TYPE;
BEGIN
OPEN c
LOOP
FETCH c INTO v_name,v_salaries;
EXIT WHEN c%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_name||' '|| v_salaries);
END LOOP;
CLOSE c;
END;
/
EXECUTE show_employees('CHICAGO');
BEGIN
show_sal('CHICAGO');
END;
/
You simply forgot the semicolon after OPEN c.
And here is how to do the same with an implicit cursor, which is much easier to deal with in my opinion:
CREATE OR REPLACE PROCEDURE show_employees(v_loc dept.loc%TYPE) AS
BEGIN
FOR rec IN
(
SELECT ename, sal
FROM emp
WHERE deptno IN (SELECT deptno FROM dept WHERE UPPER(loc) = UPPER(v_loc))
ORDER BY ename
) LOOP
DBMS_OUTPUT.PUT_LINE(rec.ename || ' ' || rec.sal);
END LOOP;
END show_employees;
Errors i get:
Function SHOW_SAL compiled
Total sum of salaries from DALLAS = 10875
PL/SQL procedure successfully completed.
Procedure SHOW_EMPLOYEES compiled
LINE/COL ERROR
9/9 PLS-00215: String length constraints must be in range (1 .. 32767)
Errors: check compiler log
Error starting at line : 40 in command -
BEGIN show_employees('CHICAGO'); END;
Error report -
ORA-06550: line 1, column 61:
PLS-00905: object HR.SHOW_EMPLOYEES is invalid
ORA-06550: line 1, column 61:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Error starting at line : 42 in command -
BEGIN
show_sal('CHICAGO');
END;
Error report -
ORA-06550: line 2, column 1:
PLS-00221: 'SHOW_SAL' is not a procedure or is undefined
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
set serveroutput on;
create or replace function show_sal (local dept.loc%type) return number as
vval number;
begin
select sum(emp.sal)
into vval
from emp inner join dept on dept.deptno = emp.deptno
where upper(dept.loc) = upper(local);
return vval;
end;
/
begin
dbms_output.put_line('Total sum of salaries from DALLAS = ' || show_sal('DALLAS'));
end;
/
-------------------------------------------------------------------------------------------------
CREATE OR REPLACE PROCEDURE show_employees(v_loc dept.loc%TYPE) AS
CURSOR C is SELECT ename,sal
FROM emp,dept
WHERE emp.deptno=dept.deptno AND UPPER(loc)=UPPER(v_loc)
ORDER BY ename ASC;
v_nume emp.ename%TYPE;
v_salariu emp.sal%TYPE;
v_tot emp.sal%TYPE;
BEGIN
v_tot:=show_sal('CHICAGO');
dbms_output.put_line('nume salar total: '||v_tot);
OPEN C;
LOOP
FETCH C INTO v_nume,v_salariu;
EXIT WHEN C%NOTFOUND;
dbms_output.put_line(v_nume||' '||v_salariu);
END LOOP;
CLOSE C;
END;
/
EXECUTE show_employees('CHICAGO');

Create table and then insert data into the new table from another table

I am creating one table name emp_inforamtion with checking that table is exist in database or not ,and if not then creating table then inserting the data from bank table in to emp_information table.
DECLARE
ncount NUMBER;
v_sql VARCHAR2(4000);
CURSOR c1
IS
SELECT bank_code,
center_code,
bank_name,
logo
FROM bank
WHERE bank_code ='607143';
BEGIN
SELECT COUNT(1) INTO ncount FROM tab WHERE tname LIKE '%EMP_INFORMATION%';
IF (ncount <= 0) THEN
DBMS_OUTPUT.PUT_LINE (ncount || 'count');
BEGIN
v_sql :=' CREATE TABLE EMP_INFORMATION
(
emp_id VARCHAR2(3),
emp_name VARCHAR2(20),
emp_salary VARCHAR2(3),
emp_department VARCHAR2(3)
)';
EXECUTE immediate v_sql;
COMMIT;
BEGIN
FOR i IN c1
LOOP
INSERT
INTO EMP_INFORMATION
(
emp_id,
emp_name,
emp_salary,
emp_department
)
VALUES
(
i.bank_code,
i.bank_name,
i.center_code,
i.logo
);
END LOOP;
END;
END;
END IF;
end;
/
found below error after executing the above cursor:
ORA-06550: line 30, column 16: PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 29, column 11: PL/SQL: SQL Statement ignored
When you create a table using execute immediate in an anonymous block, use execute immediate to insert the data into it.
DECLARE
ncount NUMBER;
v_sql VARCHAR2(4000);
CURSOR c1
IS
SELECT bank_code,
center_code,
bank_name,
logo
FROM bank
WHERE bank_code ='607143';
BEGIN
SELECT COUNT(1) INTO ncount FROM tab WHERE tname LIKE '%EMP_INFORMATION%';
IF (ncount <= 0) THEN
DBMS_OUTPUT.PUT_LINE (ncount || 'count');
BEGIN
v_sql :=' CREATE TABLE EMP_INFORMATION
(
emp_id VARCHAR2(3),
emp_name VARCHAR2(20),
emp_salary VARCHAR2(3),
emp_department VARCHAR2(3)
)';
EXECUTE IMMEDIATE v_sql;
BEGIN
FOR i IN c1
LOOP
EXECUTE IMMEDIATE 'INSERT
INTO EMP_INFORMATION
(
emp_id,
emp_name,
emp_salary,
emp_department
)
VALUES
(
:a,
:b,
:c,
:d
)' using i.bank_code, i.bank_name, i.center_code, i.logo;
END LOOP;
END;
END;
END IF;
end;
/

PL/SQL: Cursor ::Retrieve a list of employees for each department

How to retrieve list of employees for each department from table EMP into a comma-delimited new table
something like:
[column x:ie deptno] [column y:ie ename]
--------------------------
7 Jesus, María, José
5 Staz, Przemek, Tomek
6 John, Jane, Bob
below table is where I want to put my result from Function concatenate_list compilation
CREATE TABLE Z
(
x NUMBER(2) NOT NULL,
y VARCHAR2 (4000) NOT NULL
);
SET SERVEROUTPUT ON
CREATE OR REPLACE FUNCTION concatenate_list (xy_cursor IN SYS_REFCURSOR)
RETURN VARCHAR2
IS
lret VARCHAR2(30000);
ltemp VARCHAR2(30000);
BEGIN
LOOP
FETCH xy_cursor
INTO ltemp;
EXIT WHEN xy_cursor%notfound;
lret := lret || ',' || ltemp;
END LOOP;
RETURN LTRIM(lret, ',');
END;
/
SHOW ERRORS
how to insert the results from "Function concatenate_lit compile" and get a result as mentioned above.
Maybe using something like this:
INSERT INTO Z( x, y) SELECT e1.x,
concatenate_list(CURSOR(SELECT e2.y FROM EMP e2 WHERE e2.x= e1.x));
but how to set it up form inside the PL/SQL block
This may help you.
declare
type cur_name is ref cursor;
emp_name cur_name;
v_ename emp.ename%type;
v_all_ename varchar2(1000);
v_deptno emp.deptno%type;
cursor c is select deptno,cursor(select ename from emp e where e.deptno=f.deptno) from emp f group by deptno;
begin
open c;
loop
fetch c into v_deptno,emp_name;
exit when c%notfound;
loop
fetch emp_name into v_ename;
exit when emp_name%notfound;
v_all_ename:=v_all_ename||v_ename;
v_all_ename:=v_all_ename||',';
end loop;
dbms_output.put_line(v_deptno||' '||v_all_ename);
v_all_ename:='';
end loop;
close c;
end;

I'm using a collection to compare with i/p parameter ,but the last index of the collection is not getting compared

create or replace procedure save_pod_place_tag1 ( p_START_DATE in varchar2,
p_END_DATE in varchar2,
p_USER_ID in number,
p_TAG_ID in out number,
p_status out varchar2,
p_status_dtl out varchar2) is
v_rec_cnt number;
v_ID Number;
v_CNT Number;
type l_START_DATE is table of varchar2(100);
type l_END_DATE is table of varchar2(100);
v_st_dt l_START_DATE := l_START_DATE();
v_ed_dt l_END_DATE := l_END_DATE();
begin
v_ID := pod_unique_val_seq.nextval;
select to_char(start_date,'dd-mon-yyyy'),to_char(end_date,'dd-mon-yyyy')
bulk collect into v_st_dt,v_ed_dt
from pod_place_tag_tb;
for i in v_st_dt.first .. v_st_dt.count loop
if nvl(v_st_dt(i),chr(0)) < nvl(p_START_DATE,chr(0)) or nvl(v_st_dt.last,chr(0)) < nvl
(p_START_DATE,chr(0)) then
dbms_output.put_line('START_DATES are' ||' ' ||v_st_dt(i));
dbms_output.put_line('INSERTION IS ALLOWED');
else
dbms_output.put_line('INSERTION NOT ALLOWED');
end if;
end loop;
The last start _date is not getting compared and I get the o/p insertion not possible even i am passing proper p_START_DATE
I think this in roots is wrong... you cant get compare on varchar2 type expecting result as date, because varchar2 orders in other way.
example
select to_char(sysdate+level,'dd-mon-yyyy') dates from dual connect by level<=100 order by dates;
Result
01-aug-2014
01-jul-2014
01-jun-2014
01-sep-2014
02-aug-2014
02-jul-2014
02-jun-2014
03-aug-2014
03-jul-2014
03-jun-2014
04-aug-2014
04-jul-2014
04-jun-2014
...
select trunc(sysdate)+level dates from dual connect by level<=100 order by dates ASC
result
2014/05/25/
2014/05/26/
2014/05/27/
2014/05/28/
...
check anonimos block
declare
v_date1 date;
v_date2 date;
v_check_date boolean;
v_char_date1 varchar2(200);
v_char_date2 varchar2(200);
v_check_char_date boolean;
v_start_date date:=to_date('01.01.2014','dd.mm.yyyy');
v_count pls_integer:=0;
begin
for i IN 1 .. 300
LOOP
v_char_date1:=to_char(v_start_date+i,'dd-mon-yyyy');
v_date1 :=v_start_date+i;
for i1 IN 1..300
LOOP
v_char_date2:=to_char(v_start_date+i1,'dd-mon-yyyy');
v_date2 :=v_start_date+i1;
IF v_date1<v_date2 THEN
v_check_date:=true;
ELSIF v_date1>v_date2 THEN
v_check_date:=false;
END IF;
IF v_char_date1<v_char_date2 THEN
v_check_char_date:=true;
ELSIF v_char_date1>v_char_date2 THEN
v_check_char_date:=false;
END IF;
IF (v_check_char_date AND not v_check_date) THEN
dbms_output.put_line ('v_date1='||v_date1||' > '||'v_date2='||v_date2||' AND '||'v_char_date1='||v_char_date1||' < '||'v_char_date2='||v_char_date2);
exit;
ELSIF (not v_check_char_date AND v_check_date) THEN
dbms_output.put_line ('v_date1='||v_date1||' < '||'v_date2='||v_date2||' AND '||'v_char_date1='||v_char_date1||' > '||'v_char_date2='||v_char_date2);
exit;
END IF;
v_count:=v_count+1;
END LOOP;
IF (v_check_char_date AND not v_check_date) OR (not v_check_char_date AND v_check_date) THEN
exit;
END IF;
END LOOP;
dbms_output.put_line ('count='||v_count);
end;

Resources