PL/SQL cursor creation fails - sql

Cursor creation fails in SQL Developer with PL/SQL
CREATE OR REPLACE PROCEDURE print_jobs(d_name varchar2) IS
DECLARE
CURSOR curs1
IS
SELECT e.job, d.dname
FROM nikovits.emp e
JOIN nikovits.dept d ON e.deptno = d.deptno where d.dname = d_name;
rec curs%ROWTYPE;
BEGIN
OPEN curs1;
LOOP
fetch curs1 into curs;
exit when curs1%NOTFOUND;
dbms_output.put_line(to_char(rec.deptno));
END LOOP;
CLOSE curs1;
end;
Error : Encountered the symbol "DECLARE" when expecting one of the following: begin function pragma procedure subtype type

#Ferid Qenberli - When you create a procedure , you need to omit DECLARE and use AS. Try this:
CREATE OR REPLACE PROCEDURE print_jobs(d_name varchar2)
as
CURSOR curs1
IS
SELECT e.job, d.dname
FROM nikovits.emp e
JOIN nikovits.dept d ON e.deptno = d.deptno where d.dname = d_name;
rec curs1%ROWTYPE;
BEGIN
OPEN curs1;
LOOP
fetch curs1 into curs;
exit when curs1%NOTFOUND;
dbms_output.put_line(to_char(rec.deptno));
END LOOP;
CLOSE curs1;
end;
/

Please use only AS or IS and remove DECLARE keyword.
CREATE OR REPLACE PROCEDURE print_jobs(d_name varchar2) IS
CURSOR curs1 IS
SELECT e.job, d.dname
FROM nikovits.emp e
JOIN nikovits.dept d ON e.deptno = d.deptno where d.dname = d_name;
rec curs%ROWTYPE;
BEGIN
OPEN curs1;
LOOP
fetch curs1 into curs;
exit when curs1%NOTFOUND;
dbms_output.put_line(to_char(rec.deptno));
END LOOP;
CLOSE curs1;
END;

Related

Cursor and procedure/function pl sql to display employees name

I want to create a procedure/function, when user input a year and a department name, i need to display the employees' name (first and last name). This is my code so far. Any idea? Thanks!
DECLARE
CURSOR emp_cur (my_date int,my_dept departments.department_name%type) IS
SELECT e.first_name,e.last_name
FROM employees e
join departments d
on e.department_id=d.department_id
where d.department_name=my_dept and my_date=extract(year from e.hire_date);
PROCEDURE emp_excesspaid IS
v_first employees.first_name%TYPE;
v_last employees.last_name%TYPE;
BEGIN
LOOP
FETCH emp_cur INTO v_first, v_last;
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_first||' '||v_last);
END LOOP;
END;
end;
You can make it simple as follows:
CREATE OR REPLACE PROCEDURE PROC_NAME(
P_IN_DEPT_NAME IN VARCHAR2,
P_IN_YEAR IN NUMBER
) AS
BEGIN
For D in (SELECT e.first_name, e.last_name
FROM employees e
join departments d
on e.department_id = d.department_id
where d.department_name = P_IN_DEPT_NAME
and extract(year from e.hire_date) = P_IN_YEAR)
LOOP
DBMS_OUTPUT.PUT_LINE(D.FIRST_NAME || ' ' || D.LAST_NAME);
END LOOP;
END;
/

I am getting error during executing the function "subquery must return only one column"

I am getting error as "subquery must return only one column". Because i have more employees in each department. Tell me the solution to fix this issue
CREATE OR REPLACE FUNCTION dept_emp()
RETURNS TEXT AS
$$
DECLARE
cur_dept CURSOR FOR SELECT dept_name FROM dept;
cur_emp CURSOR FOR SELECT employee_id,dob,department FROM emp;
d RECORD;
e RECORD;
BEGIN
FOR d IN SELECT dept_name FROM dept
LOOP
FOR e IN SELECT employee_id,dob,department FROM emp
LOOP
RAISE NOTICE 'Department: %',d.dept_name;
RETURN (SELECT employee_id,dob FROM emp WHERE d.dept_name=e.department);
END LOOP;
END LOOP;
END;
$$ LANGUAGE 'plpgsql';

How to set an object as an out parameter?

I have written a procedure in PL/SQL and want to return a EMP type object. Is it possible to do that? If yes, how can I do it?
Here is the code:
CREATE OR REPLACE
PROCEDURE get_emp_rs (p_deptno IN emp.deptno%TYPE,
p_recordset OUT emp_det) AS
emp_details emp_det;
BEGIN
OPEN p_recordset FOR
SELECT ename,
empno
FROM emp
WHERE deptno = p_deptno
ORDER BY ename;
fetch p_recordset into emp_details;
--exit when p_recordset%notfound;
--end loop;
--for indx in p_recordset
--loop
emp_details.ename:= 'test';
--end loop;
END get_emp_rs;
/
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
l_cursor emp_det;
--l_cur emp_det;
--l_ename emp.ename%TYPE;
--l_empno emp.empno%TYPE;
l_deptno emp.deptno%TYPE;
BEGIN
l_cur:=get_emp_rs ('30',
l_cursor);
dbms_output.put_line('low');
/*LOOP
FETCH l_cursor
INTO l_ename, l_empno, l_deptno;
EXIT WHEN l_cursor%NOTFOUND;*/
DBMS_OUTPUT.PUT_LINE(l_cursor.ename || ' | ' || l_cursor.empno);
end;
/
I want to get the ename and empno after finally update in the procedure.
How can I do it? If there is any better way of doing this please suggest me.
And also please suggest me how I can do it in this way. I cannot use any functions here that's the only obligation. Also please let me know if there is a way of doing this using.
In your example (Table EMP) a single EMP Record shouldn't be selected by the department number. Use the EMPNO instead.
The following is a quick solution and hopefully self-explainable:
SET SERVEROUTPUT ON;
SET FEEDBACK OFF;
CLEAR;
--Define the dataset object
CREATE TYPE EMP_DET AS OBJECT (
EMPNO NUMBER(4),
ENAME VARCHAR2(10)
);
/
--Define a collection of dataset objects
CREATE TYPE EMP_DET_LIST IS TABLE OF EMP_DET;
/
--Get a SINGLE record into the OUT-Variable identified by EMP PK EMPNO
CREATE OR REPLACE PROCEDURE GET_EMP_RS(P_EMPNO IN EMP.EMPNO%TYPE,
P_RECORDSET IN OUT EMP_DET) AS
BEGIN
--Create the return object inside SQL
SELECT EMP_DET(EMPNO, ENAME)
INTO P_RECORDSET
FROM EMP
WHERE EMPNO = P_EMPNO;
P_RECORDSET.ENAME := 'test';
EXCEPTION
WHEN NO_DATA_FOUND THEN
--Return NULL if employee not found
P_RECORDSET := NULL;
END GET_EMP_RS;
/
--Get a LIST OF employees by department
CREATE OR REPLACE PROCEDURE GET_EMP_LIST(P_DEPTNO IN EMP.DEPTNO%TYPE,
P_RECORDLIST OUT EMP_DET_LIST) AS
TYPE C_CURSOR IS REF CURSOR; -- <-- For the explicit cursor solution only
C_EMP_RS C_CURSOR; -- <-- For the explicit cursor solution only
V_RS EMP_DET; -- <-- For the explicit cursor solution only
BEGIN
--Initialize out object
P_RECORDLIST := EMP_DET_LIST();
--Create the return object inside SQL
--via bulk collect
/*
SELECT EMP_DET(EMPNO,ENAME)
BULK COLLECT INTO INTO P_RECORDLIST
FROM EMP
WHERE DEPTNO = P_DEPTNO;
*/
--with manipulation of records
--use a FOR-LOOP with implizit cursor
/*
FOR L_RS IN (SELECT EMP_DET(EMPNO, ENAME) EMP_RS
FROM EMP
WHERE DEPTNO = P_DEPTNO) LOOP
L_RS.EMP_RS.ENAME := 'TEST';
P_RECORDLIST.EXTEND;
P_RECORDLIST(P_RECORDLIST.LAST) := L_RS.EMP_RS;
NULL;
END LOOP;
*/
--or define an explicit cursor and LOOP-FETCH
OPEN C_EMP_RS FOR
SELECT EMP_DET(EMPNO, ENAME) EMP_RS
FROM EMP
WHERE DEPTNO = P_DEPTNO;
LOOP
FETCH C_EMP_RS
INTO V_RS;
EXIT WHEN C_EMP_RS%NOTFOUND;
V_RS.ENAME := 'TEST';
P_RECORDLIST.EXTEND;
P_RECORDLIST(P_RECORDLIST.LAST) := V_RS;
END LOOP;
CLOSE C_EMP_RS;
END GET_EMP_LIST;
/
--**************************
-- Test
--**************************
DECLARE
L_CURSOR EMP_DET;
L_LIST EMP_DET_LIST;
BEGIN
DBMS_OUTPUT.PUT_LINE('---- Single EMP ----');
GET_EMP_RS(7369, L_CURSOR);
IF (L_CURSOR IS NOT NULL) THEN
DBMS_OUTPUT.PUT_LINE(L_CURSOR.ENAME || ' | ' || L_CURSOR.EMPNO);
END IF;
DBMS_OUTPUT.PUT_LINE('---- EMP List ----');
GET_EMP_LIST(30, L_LIST);
IF (L_LIST.count > 0 ) THEN
FOR L_I IN L_LIST.FIRST .. L_LIST.LAST LOOP
DBMS_OUTPUT.PUT_LINE(L_LIST(L_I).ENAME || ' | ' || L_LIST(L_I).EMPNO);
END LOOP;
END IF;
END;
/
DROP PROCEDURE GET_EMP_RS;
DROP PROCEDURE GET_EMP_LIST;
DROP TYPE EMP_DET_LIST;
DROP TYPE EMP_DET;
Output:
---- Single EMP ----
test | 7369
---- EMP List ----
TEST | 7499
TEST | 7521
TEST | 7654
TEST | 7698
TEST | 7844
TEST | 7900
SQL>

Declaring a cursor inside sql stored procedure goes 'success with compilation errors' every time. Is my syntax wrong? I am using Oracle 11g

CREATE OR REPLACE PROCEDURE deptShow (tempCID IN VARCHAR2) IS
CURSOR temp_cursor IS SELECT D.DEPARTMENT_ID dept_id, D.DEPARTMENT_NAME dept_name
FROM DEPARTMENTS D
JOIN LOCATIONS L ON (D.LOCATION_ID=L.LOCATION_ID)
JOIN COUNTRIES C ON (L.COUNTRY_ID=C.COUNTRY_ID)
WHERE C.COUNTRY_ID=tempCID;
BEGIN
FOR temp_row IN temp_cursor
LOOP
DBMS_OUTPUT.PUT_LINE(temp_row.dept_id||temp_row.dept_name);
END LOOP;
END;

PL/SQL duplicate

I'm executing the following PL/SQL script on sqlplus :
declare
cursor c is select sal, empno, ename from emp where ((comm is null and sal>2000) or (comm is not null and (sal+comm)>2000));
v_sal emp.sal%type;
v_empno emp.sal%type;
v_ename emp.ename%type;
begin
open c;
loop
fetch c into v_sal,v_empno,v_ename;
insert into temp values(v_sal,v_empno,v_ename);
exit when(c%notfound);
end loop;
close c;
end;
/
I obtain all the n-uplets I want but the last one is duplicated.
Put the exit statement before insert.