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

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;

Related

Error in executing plsql procedure (value larger than specified precision allowed for this column)

Here is my procedure where i want to insert values with the conditions like emp id start with sequence 131, phone number must be 13 digits, hire date not greater than sys date and salary not greater than 50,000. while executing im facing error . how to solve this.
create or replace procedure empinsert AS
cursor employee is select length(PHONE_NUMBER),HIRE_DATE,SAL from emp;
e_mobile_no emp.phone_number%type;
e_hire_date emp.hire_date%type;
e_salary emp.sal%type;
Begin
open employee ;
loop
fetch employee into e_mobile_no,e_hire_date,e_salary;
if ( e_mobile_no = 13 and e_hire_date < sysdate and e_salary <=50000 ) then
INSERT INTO EMP (EMP_ID,
EMP_NAME,
EMAIL,
PHONE_NUMBER,
HIRE_DATE,
JOB_ID,
SAL)
values(empinc.nextval, 'ramji','ramji#gmail.com','8975432109875','10/07/2021','JUN_TECH',40000);
else
exit;
end if;
end loop;
end;
/

PL/SQL: I get expression 'I' cannot be used as an assignment target

My code:
create table info(str varchar2(30));
declare
cursor c(job emp_ast.job_id%type, dep emp_ast.department_id%type) is select employee_id
from emp_ast
where job_id=job and department_id=dep;
type t_job is table of emp_ast.job_id%type;
t t_job:=t_job();
emp emp_ast.employee_id%type;
i number(3);
begin
select job_id
bulk collect into t
from emp_ast;
for i in 10..270 loop
for j in 1..t.count loop
open c(i, t(j));
loop
fetch c into emp;
insert into info
values (i||' '||t(j)||' '||emp);
exit when c%notfound;
end loop;
i:=i+10;
end loop;
end loop;
end;
/
I get "expression 'I' cannot be used as an assignment target", reffering to the line where I increment i by 10. I am trying to save the department_id, employee_id and job_id as a string in a table for each department and each job.
At the point where you get that message, i refers to the loop control variable i defined in the line for i in 10..270 loop, not the int(3) variable defined earlier. In PL/SQL a loop definition defines a variable which is only accessible inside the loop, and which you cannot alter. I suggest you change the name of one or the other to make them unique.
EDIT
PL/SQL doesn't provide a way to step by more than 1 in a computed FOR loop. Instead, you will need to compute the desired department number value within the loop:
DECLARE
CURSOR c(job EMP_AST.JOB_ID%TYPE,
dep EMP_AST.DEPARTMENT_ID%TYPE)
IS SELECT EMPLOYEE_ID
FROM EMP_AST
WHERE JOB_ID = job AND
DEPARTMENT_ID = dep;
TYPE t_job IS TABLE OF EMP_AST.JOB_ID%TYPE;
t t_job := t_job();
emp EMP_AST.EMPLOYEE_ID%TYPE;
nDepartment NUMBER;
BEGIN
SELECT job_id
BULK COLLECT INTO t
FROM EMP_AST;
FOR i IN 1..27 LOOP
nDepartment := i * 10;
FOR j IN 1..t.COUNT LOOP
OPEN c(t(j), nDepartment);
LOOP
FETCH c INTO emp;
INSERT INTO info
VALUES (nDepartment || ' ' || t(j) || ' ' || emp);
EXIT WHEN c%notfound;
END LOOP; -- cursor c
CLOSE c;
END LOOP; -- j
END LOOP; -- i
END;
/
Note that in the code above the nDepartment value is computed within the i loop, which now increments from 1 to 27 instead of going from 10 to 270.

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 );

Use cursor in LOOP in new QUERY

"I missing the forest through the trees..."
I want to query each column of a table which I retrieve in a FOR LOOP, but the inner query doesn't return the right thing.
Seems that the inner query not use the current column_name.
DECLARE
v_max_TS TIMESTAMP;
BEGIN
FOR cols IN (SELECT column_name FROM all_tab_cols WHERE table_name = '<tablename>')
LOOP
SELECT
MAX(CURR_TIMESTAMP) INTO v_max_TS
FROM <tablename>
WHERE cols.column_name IS NOT NULL
ORDER BY TO_TIMESTAMP(CURR_TIMESTAMP,'MM/DD/YYYY HH24:MI:SS') DESC;
dbms_output.put_line(cols.column_name || ' ' || v_max_TS);
END LOOP;
END;
Apart from the fact that your query doesn't make much sense (as Boneist wrote as a comment), that won't work as you need to use dynamic SQL (execute immediate) for such a purpose.
Here's an example based on Scott's schema. Have a look, adjust it if necessary.
SQL> set serveroutput on
SQL> declare
2 l_str varchar2(200); -- will hold the SELECT statement
3 v_max varchar2(30);
4 begin
5 for cols in (select column_name
6 from all_tab_cols
7 where table_name = 'DEPT'
8 )
9 loop
10 l_str := 'select max(' || cols.column_name ||') from dept';
11 execute immediate l_str into v_max;
12 dbms_output.put_line(cols.column_name ||': '|| v_max);
13 end loop;
14 end;
15 /
DEPTNO: 40
DNAME: SALES
LOC: NEW YORK
PL/SQL procedure successfully completed.
SQL>

PL/SQL functions [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Homework on PL/SQL FUNCTIONS
plsql functions
Function:
function to Display_Employee_Name_In_Uppercase that accepts the Employee_ID from the Empoyees table and returns the first and the last name of the employee in uppercase.
Write a small PL/SQL program to display the names of the employees whose Employee_IDs are 107, 200 and 205.
this is what I have done I didnt know how to complete it
can help ?
CREATE OR REPLACE FUNCTION disp (emp_id in varchar20) return emp_name
select into emp_name
fname||lname
from employees
where employee_id=emp_id
END disp ;
Something like this...
CREATE OR REPLACE
FUNCTION Fn_Display(p_empId IN VARCHAR2)
RETURN VARCHAR2
IS
empName VARCHAR2(100);
BEGIN
BEGIN
SELECT UPPER(first_name || ' ' || last_name)
INTO empName
FROM Employees
WHERE employee_id = p_empId;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE NO_DATA_FOUND
END;
RETURN empName;
END Fn_Display;
You can call this function wherever you want. here is a sample...
DECLARE
empId VARCHAR2(100);
empName VARCHAR2(100);
BEGIN
empId := &ENTER_EMPLOYEE_ID;
empName := Fn_Display(empId);
DBMS_OUTPUT.PUT_LINE('Employee Name: '||empName);
END;
You could try this code, maybe this one works for you:
CREATE OR REPLACE FUNCTION disp (emp_id in varchar2) return varchar2 IS
emp_name varchar2(256);
BEGIN
select UPPER(fname || ' ' || lname)
into emp_name
from employees
where employee_id = emp_id;
return emp_name;
END disp;

Resources