无法引用oracle pl / sql的游标实例

时间:2015-02-28 10:13:43

标签: oracle oracle11g

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”的无效引用错误,为什么?我还在学习阶段,很抱歉胡说八道。感谢

1 个答案:

答案 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前缀。

我认为你将此作为一种学习练习,否则这一切都可以更简单地完成。