CREATE OR REPLACE PROCEDURE employee_info_all_in_one
(p_id IN NUMBER)
IS
CURSOR c_city IS
(SELECT l.city
FROM employees e
INNER JOIN departments d
ON (e.department_id = d.department_id)
INNER JOIN locations l
ON (l.location_id = d.location_id)
WHERE e.employee_id = p_id);
CURSOR c_manager IS
(SELECT e1.last_name
FROM employees e1
INNER JOIN
employees e2
ON (e1.employee_id = e2.manager_id)
WHERE e2.employee_id = p_id);
CURSOR c_department_name IS
(SELECT department_name
FROM employees e
INNER JOIN
departments d
ON (e.department_id = d.department_id)
WHERE e.employee_id = p_id);
TYPE EmpRecTyp IS RECORD
( v_annual_sal NUMBER(9,2),
v_monthly_sal NUMBER(9,2),
v_last_name VARCHAR2(10),
v_deptno NUMBER(3),
v_length NUMBER(2),
v_tenure NUMBER(5),
v_job_id VARCHAR2(20),
v_hire_date DATE,
v_city VARCHAR(25),
v_commission_pct NUMBER(2,2),
v_phone_number VARCHAR2(20),
v_manager VARCHAR2(20),
v_comm_calc NUMBER(10,2),
v_email VARCHAR2(10),
v_department VARCHAR2(20),
v_count NUMBER(4)
);
TYPE EmpRecTyp IS REF CURSOR;
emp_c_v EmpRecTyp;
BEGIN
DBMS_OUTPUT.PUT_LINE('Welcome to the summary of an employee based on his unique id');
DBMS_OUTPUT.PUT_LINE('============================================================');
SELECT salary, last_name, department_id,
TRUNC(MONTHS_BETWEEN(SYSDATE,hire_date),0), job_id,
hire_date, commission_pct, phone_number, email
INTO emp_c_v.v_monthly_sal, emp_c_v.v_last_name, emp_c_v.v_deptno,
emp_c_v.v_tenure, emp_c_v.v_job_id, emp_c_v.v_hire_date, emp_c_v.v_commission_pct,
emp_c_v.v_phone_number, emp_c_v.v_email
FROM employees
WHERE employee_id = p_id;
emp_c_v.v_count := SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE(emp_c_v.v_count||' row retrieved...');
DBMS_OUTPUT.PUT_LINE('=============================');
emp_c_v.v_annual_sal := emp_c_v.v_monthly_sal * 12;
emp_c_v.v_length := LENGTH(emp_c_v.v_last_name);
DBMS_OUTPUT.PUT_LINE('Employee:-> ' || emp_c_v.v_last_name || ' ,and his name contains: ' || emp_c_v.v_length ||' chars');
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE(q'[Belong's to department: ]' || emp_c_v.v_deptno);
DBMS_OUTPUT.PUT_LINE('=============================');
IF (emp_c_v.v_monthly_sal < emp_c_v.v_annual_sal)
THEN
DBMS_OUTPUT.PUT_LINE('Has a annual salary of:-> ' || emp_c_v.v_annual_sal);
ELSE
DBMS_OUTPUT.PUT_LINE('Something wrong in the formula!');
END IF;
IF emp_c_v.v_commission_pct IS NULL
THEN
DBMS_OUTPUT.PUT_LINE('No Commission added to the annual salary!');
ELSE
DBMS_OUTPUT.PUT_LINE('Commission percentage to the salary is:-> '|| emp_c_v.v_commission_pct ||'%');
emp_c_v.v_comm_calc := (emp_c_v.v_annual_sal * emp_c_v.v_commission_pct) + emp_c_v.v_annual_sal;
DBMS_OUTPUT.PUT_LINE('And calculated with annual salary is:->' ||v_comm_calc);
END IF;
DBMS_OUTPUT.PUT_LINE('Working for:-> '|| emp_c_v.v_tenure || ' months as '|| emp_c_v.v_job_id);
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE('Started in:-> '|| emp_c_v.v_hire_date);
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE('Phone number:-> '||emp_c_v.v_phone_number);
DBMS_OUTPUT.PUT_LINE('=============================');
DBMS_OUTPUT.PUT_LINE('Email:-> '||emp_c_v.v_email);
DBMS_OUTPUT.PUT_LINE('=============================');
OPEN c_city;
FETCH c_city INTO v_city;
IF c_city%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Location:-> '||emp_c_v.v_city);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee location unknown');
END IF;
CLOSE c_city;
OPEN c_manager;
FETCH c_manager INTO emp_c_v.v_manager;
IF c_manager%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Is in the eyes of manager:-> '||emp_c_v.v_manager);
ELSE
DBMS_OUTPUT.PUT_LINE('Slave '||emp_c_v.v_last_name||' is free!');
END IF;
CLOSE c_manager;
OPEN c_department_name;
FETCH c_department_name INTO emp_c_v.v_department;
IF c_department_name%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Department Name:-> '||emp_c_v.v_department);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee ' ||emp_c_v.v_last_name||' belongs to no department!');
END IF;
DBMS_OUTPUT.PUT_LINE('================================');
DBMS_OUTPUT.PUT_LINE('Checking for employee with id '|| p_id ||'..');
IF (check_sal2(p_id) IS NULL)
THEN
DBMS_OUTPUT.PUT_LINE('The function returned NULL due to exception, therefore employee does not exist!');
ELSIF (check_sal2(p_id))
THEN
DBMS_OUTPUT.PUT_LINE('Employees salary > average of department '||emp_c_v.v_deptno||' where he belongs.');
ELSE
DBMS_OUTPUT.PUT_LINE('Salary < average of department '||emp_c_v.v_deptno||', where he belongs.');
END IF;
DBMS_OUTPUT.PUT_LINE('=====================================================');
END;
最初我只有在这个子程序中声明的简单变量(v _...),但我想利用真正的游标变量,比如指针?我想。所以我修改并定义了一种记录,并为其中的变量或字段引用了一个游标“... IS REF CURSOR”。但是当我编译整个事情时,我得到了对变量“emp_c_v”的无效引用错误,为什么?我还在学习阶段,很抱歉胡说八道。感谢
答案 0 :(得分:2)
游标是指向结果集(sort of)的指针,而不是指向单个记录的指针。您无法修改结果集。在这种情况下,指针实际上不会指向任何内容,因为它没有(从查询中)将结果集指向指向。
如果删除引用游标并使变量成为记录类型,则代码几乎会编译;所以代替:
TYPE EmpCurTyp IS REF CURSOR;
emp_c_v EmpCurTyp;
使用:
emp_c_v EmpRecTyp;
在更改参考文献时,您还错过了几个地方:
DBMS_OUTPUT.PUT_LINE('And calculated with annual salary is:->' ||v_comm_calc);
和
FETCH c_city INTO v_city;
...两者分别需要emp_c_v.
和v_comm_calc
之前的v_city
前缀。
我认为你将此作为一种学习练习,否则这一切都可以更简单地完成。