光标

时间:2016-05-14 20:10:37

标签: oracle plsql

我需要编写一个游标,用于显示员工列表,选择mit参数从from_employee和to_employee两个例外。首先需要在没有选择行时工作,而另一个选择只有一行时需要工作。我的代码只是阻止sqldeveloper的所有时间,它开始神经紧张。我需要帮助!!!

 `set serveroutput on;
set echo on;
CREATE OR REPLACE PROCEDURE output_employee_set (
 from_employee IN NUMBER,
 to_employee IN NUMBER,
 ascending_order IN BOOLEAN)
 IS
    v_id            EMP.EMPLOYEE_ID%TYPE;
    v_ename         EMP.FIRST_NAME%TYPE;
    v_surname       EMP.LAST_NAME%TYPE;
    v_email         EMP.EMAIL%TYPE;
    v_telefon       EMP.PHONE_NUMBER%TYPE;
    v_hiredate      EMP.HIRE_DATE%TYPE;
    v_sal           EMP.SALARY%TYPE;
    v_job           JOBS.JOB_TITLE%TYPE;
    v_dname         DEPARTMENTS.DEPARTMENT_NAME%TYPE;
    v_manager       EMP.LAST_NAME%TYPE;
    one_element     Exception;
    no_element      Exception;
    counter         NUMBER;

    CURSOR emp_cur IS
       SELECT  e.EMPLOYEE_ID,e.FIRST_NAME,e.LAST_NAME,e.EMAIL,e.PHONE_NUMBER,e.HIRE_DATE,e.SALARY,j.JOB_TITLE,d.DEPARTMENT_NAME,m.LAST_NAME

        FROM emp e LEFT OUTER JOIN employees m ON (m.employee_id = e.manager_id), DEPARTMENTS d, JOBS j
        WHERE 
           e.DEPARTMENT_ID = d.DEPARTMENT_ID
          AND e.JOB_ID=j.JOB_ID
          ORDER BY e.EMPLOYEE_ID ;


BEGIN
SELECT COUNT(e.employee_id) INTO counter FROM emp e LEFT OUTER JOIN employees m ON (m.employee_id = e.manager_id), DEPARTMENTS d, JOBS j
        WHERE 
           e.DEPARTMENT_ID = d.DEPARTMENT_ID
          AND e.JOB_ID=j.JOB_ID
          ORDER BY e.EMPLOYEE_ID ;

 IF   ascending_order  THEN
    OPEN emp_cur;

    LOOP
    IF v_id BETWEEN from_employee AND to_employee THEN
        FETCH emp_cur INTO v_id,v_ename,v_surname,v_email,v_telefon,v_hiredate,v_sal,v_job,v_dname,v_manager;

        IF emp_cur%NOTFOUND THEN RAISE no_element;
        EXIT;
            ELSE
            FETCH emp_cur INTO v_id,v_ename,v_surname,v_email,v_telefon,v_hiredate,v_sal,v_job,v_dname,v_manager;
             IF counter=1 THEN RAISE one_element;
             ELSE

    DBMS_OUTPUT.PUT_LINE('Number         : ' || v_id);
    DBMS_OUTPUT.PUT_LINE('Name           : ' || v_ename||' '||v_surname);
    DBMS_OUTPUT.PUT_LINE('Email          : ' || v_email);
    DBMS_OUTPUT.PUT_LINE('Telefon NR.    : ' || v_telefon);
    DBMS_OUTPUT.PUT_LINE('Eingestellt am : ' || v_hiredate);
    DBMS_OUTPUT.PUT_LINE('Gehalt         : ' || v_sal);
    DBMS_OUTPUT.PUT_LINE('Beruf ID       : ' || v_job);
    DBMS_OUTPUT.PUT_LINE('Department     : ' || v_dname);
    DBMS_OUTPUT.PUT_LINE('Vorgesetzter   : ' || v_manager);
     END IF;
     END IF;
    END IF;
    END LOOP;

    CLOSE emp_cur;



 END IF;
   EXCEPTION 
   WHEN one_element THEN 
    DBMS_OUTPUT.PUT_LINE('Just one employee was selected');
    WHEN no_element THEN 
    DBMS_OUTPUT.PUT_LINE('No employees were selected'); 
END;
/
 ` 

3 个答案:

答案 0 :(得分:0)

您的代码中存在少量小错误。

第一个错误:(m.employee_id = e.manager_id) - 它应该是:(e.employee_id = m.manager_id)

第二个错误:定义光标时,必须使用manager last_name的别名,因为您首先选择employer's last name,并且会有两行称为LAST_NAME

第三个错误:您在该LOOP中没有初始化v_id。 因此,您必须输入循环,在employee_ID中获取v_id,然后检查v_idfrom_employee之间是否to_employee

我使用FOR LOOP重写了你的代码来从光标中获取并且它工作正常。

以下是代码:

CREATE OR REPLACE PROCEDURE output_employee_set (
from_employee IN NUMBER,
to_employee IN NUMBER,
ascending_order IN BOOLEAN)
IS
   v_id            EMP.EMPLOYEE_ID%TYPE;
   v_ename         EMP.FIRST_NAME%TYPE;
   v_surname       EMP.LAST_NAME%TYPE;
   v_email         EMP.EMAIL%TYPE;
   v_telefon       EMP.PHONE_NUMBER%TYPE;
   v_hiredate      EMP.HIRE_DATE%TYPE;
   v_sal           EMP.SALARY%TYPE;
   v_job           JOBS.JOB_TITLE%TYPE;
   v_dname         DEPARTMENTS.DEPARTMENT_NAME%TYPE;
   v_manager       EMP.LAST_NAME%TYPE;
   one_element     Exception;
   no_element      Exception;
   counter         NUMBER;

   CURSOR emp_cur IS
     SELECT  e.EMPLOYEE_ID, e.FIRST_NAME,
           e.LAST_NAME, e.EMAIL,
           e.PHONE_NUMBER, e.HIRE_DATE, 
           e.SALARY,  j.JOB_TITLE,  d.DEPARTMENT_NAME, m.LAST_NAME as manager_name

    FROM emp e LEFT OUTER JOIN employees m ON (e.employee_id = m.manager_id), DEPARTMENTS d, JOBS j
    WHERE 
       e.DEPARTMENT_ID = d.DEPARTMENT_ID
      AND e.JOB_ID=j.JOB_ID
      ORDER BY e.EMPLOYEE_ID ;    
BEGIN

   SELECT COUNT(e.employee_id) INTO counter FROM emp e LEFT OUTER JOIN employees m ON (e.employee_id = m.manager_id), DEPARTMENTS d, JOBS j
      WHERE 
         e.DEPARTMENT_ID = d.DEPARTMENT_ID
        AND e.JOB_ID = j.JOB_ID
        ORDER BY e.EMPLOYEE_ID ;

 --Updated
 IF (counter = 0 ) THEN
    RAISE no_element;
 END IF;  

 IF   ascending_order = true  THEN    
   FOR index_cursor IN emp_cur LOOP        

    v_id := index_cursor.employee_id; 
    IF (v_id >= from_employee AND v_id <= to_employee) THEN

          v_ename := index_cursor.first_name;
          v_surname := index_cursor.last_name;
          v_email := index_cursor.email;
          v_telefon := index_cursor.phone_number;
          v_hiredate := index_cursor.hire_date;
          v_sal := index_cursor.salary;
          v_job := index_cursor.job_title;
          v_dname := index_cursor.department_name;
          v_manager := index_cursor.manager_name;

          -- Or you can directly print the content using 
          -- DBMS_OUTPUT.PUT_LINE('Number :' || index_cursor.employee_id);

          DBMS_OUTPUT.PUT_LINE('Number         : ' || v_id);
          DBMS_OUTPUT.PUT_LINE('Name           : ' || v_ename||' '||v_surname);
          DBMS_OUTPUT.PUT_LINE('Email          : ' || v_email);
          DBMS_OUTPUT.PUT_LINE('Telefon NR.    : ' || v_telefon);
          DBMS_OUTPUT.PUT_LINE('Eingestellt am : ' || v_hiredate);
          DBMS_OUTPUT.PUT_LINE('Gehalt         : ' || v_sal);
          DBMS_OUTPUT.PUT_LINE('Beruf ID       : ' || v_job);
          DBMS_OUTPUT.PUT_LINE('Department     : ' || v_dname);
          DBMS_OUTPUT.PUT_LINE('Vorgesetzter   : ' || v_manager);
          DBMS_OUTPUT.PUT_LINE('');

          --Update
          IF (counter = 1 ) THEN
            EXIT;
          END IF;   

    END IF;
  END LOOP;
  IF (counter = 1) THEN
    RAISE one_element;
  END IF;
END IF;
 EXCEPTION 
  WHEN one_element THEN 
    DBMS_OUTPUT.PUT_LINE('Just one employee was selected');
  WHEN no_element THEN 
    DBMS_OUTPUT.PUT_LINE('No employees were selected'); 
END;
/

答案 1 :(得分:0)

为什么不在计算&#39;计数器&#39;的查询中插入条件EMPLOYEE_ID?并形成&#39; emp_cur&#39;分别? 对我来说是这样的(代码基于@PianoSong的变体):

PROCEDURE output_employee_set (
    from_employee IN NUMBER,
    to_employee IN NUMBER,
    ascending_order IN BOOLEAN)
    IS
       v_id            EMP.EMPLOYEE_ID%TYPE;
       v_ename         EMP.FIRST_NAME%TYPE;
       v_surname       EMP.LAST_NAME%TYPE;
       v_email         EMP.EMAIL%TYPE;
       v_telefon       EMP.PHONE_NUMBER%TYPE;
       v_hiredate      EMP.HIRE_DATE%TYPE;
       v_sal           EMP.SALARY%TYPE;
       v_job           JOBS.JOB_TITLE%TYPE;
       v_dname         DEPARTMENTS.DEPARTMENT_NAME%TYPE;
       v_manager       EMP.LAST_NAME%TYPE;
       one_element     Exception;
       no_element      Exception;
       counter         NUMBER;

       CURSOR emp_cur IS
         SELECT  e.EMPLOYEE_ID, e.FIRST_NAME,
               e.LAST_NAME, e.EMAIL,
               e.PHONE_NUMBER, e.HIRE_DATE, 
               e.SALARY,  j.JOB_TITLE,  d.DEPARTMENT_NAME, m.LAST_NAME as manager_name

        FROM emp e LEFT OUTER JOIN employees m ON (e.employee_id = m.manager_id), DEPARTMENTS d, JOBS j
        WHERE 
           e.DEPARTMENT_ID = d.DEPARTMENT_ID
          AND e.JOB_ID=j.JOB_ID
          AND e.EMPLOYEE_ID>=from_employee
          AND e.EMPLOYEE_ID<=to_employee
          ORDER BY e.EMPLOYEE_ID ;    
    BEGIN

       SELECT COUNT(e.employee_id) INTO counter FROM emp e LEFT OUTER JOIN employees m ON (e.employee_id = m.manager_id), DEPARTMENTS d, JOBS j
          WHERE 
             e.DEPARTMENT_ID = d.DEPARTMENT_ID
            AND e.JOB_ID = j.JOB_ID
            AND e.EMPLOYEE_ID>=from_employee
            AND e.EMPLOYEE_ID<=to_employee
            ORDER BY e.EMPLOYEE_ID ;

     IF   ascending_order = true  THEN   
       IF (counter = 0 ) THEN
          RAISE no_element;
       ELSIF (counter = 1 ) THEN
          RAISE one_element;
       END IF;  

       FOR index_cursor IN emp_cur LOOP        
              v_ename := index_cursor.first_name;
              v_surname := index_cursor.last_name;
              v_email := index_cursor.email;
              v_telefon := index_cursor.phone_number;
              v_hiredate := index_cursor.hire_date;
              v_sal := index_cursor.salary;
              v_job := index_cursor.job_title;
              v_dname := index_cursor.department_name;
              v_manager := index_cursor.manager_name;

              DBMS_OUTPUT.PUT_LINE('Number         : ' || v_id);
              DBMS_OUTPUT.PUT_LINE('Name           : ' || v_ename||' '||v_surname);
              DBMS_OUTPUT.PUT_LINE('Email          : ' || v_email);
              DBMS_OUTPUT.PUT_LINE('Telefon NR.    : ' || v_telefon);
              DBMS_OUTPUT.PUT_LINE('Eingestellt am : ' || v_hiredate);
              DBMS_OUTPUT.PUT_LINE('Gehalt         : ' || v_sal);
              DBMS_OUTPUT.PUT_LINE('Beruf ID       : ' || v_job);
              DBMS_OUTPUT.PUT_LINE('Department     : ' || v_dname);
              DBMS_OUTPUT.PUT_LINE('Vorgesetzter   : ' || v_manager);
              DBMS_OUTPUT.PUT_LINE('');
      END LOOP;
    END IF;
     EXCEPTION 
      WHEN one_element THEN 
        DBMS_OUTPUT.PUT_LINE('Just one employee was selected');
      WHEN no_element THEN 
        DBMS_OUTPUT.PUT_LINE('No employees were selected'); 
  END;

答案 2 :(得分:0)

      set serveroutput on;
      set echo on;
      CREATE OR REPLACE PROCEDURE output_employee_set (
       from_employee IN NUMBER,
       to_employee IN NUMBER,
       ascending_order IN BOOLEAN)
       IS

          v_id            EMP.EMPLOYEE_ID%TYPE;
          v_ename         EMP.FIRST_NAME%TYPE;
          v_surname       EMP.LAST_NAME%TYPE;
          v_email         EMP.EMAIL%TYPE;
          v_telefon       EMP.PHONE_NUMBER%TYPE;
          v_hiredate      EMP.HIRE_DATE%TYPE;
          v_sal           EMP.SALARY%TYPE;
          v_job           JOBS.JOB_TITLE%TYPE;
          v_dname         DEPARTMENTS.DEPARTMENT_NAME%TYPE;
          v_manager       EMP.LAST_NAME%TYPE;
          one_element     Exception;
         no_element      Exception;
         counter         NUMBER;

          CURSOR emp_cur IS
             SELECT  e.EMPLOYEE_ID,e.FIRST_NAME,e.LAST_NAME,e.EMAIL,e.PHONE_NUMBER,e.HIRE_DATE,e.SALARY,j.JOB_TITLE,d.DEPARTMENT_NAME,m.LAST_NAME

              FROM emp e, emp m, DEPARTMENTS d, JOBS j
              WHERE 
                 e.DEPARTMENT_ID = d.DEPARTMENT_ID
                AND e.MANAGER_ID=m.EMPLOYEE_ID
                AND e.JOB_ID=j.JOB_ID
                ORDER BY e.EMPLOYEE_ID ;

            CURSOR emp_cur_desc IS
             SELECT  e.EMPLOYEE_ID,e.FIRST_NAME,e.LAST_NAME,e.EMAIL,e.PHONE_NUMBER,e.HIRE_DATE,e.SALARY,j.JOB_TITLE,d.DEPARTMENT_NAME,m.LAST_NAME

              FROM emp e, emp m, DEPARTMENTS d, JOBS j
              WHERE 
                 e.DEPARTMENT_ID = d.DEPARTMENT_ID
                AND e.MANAGER_ID=m.EMPLOYEE_ID
                AND e.JOB_ID=j.JOB_ID
                ORDER BY e.EMPLOYEE_ID DESC;
      BEGIN
      DBMS_OUTPUT.ENABLE(1000000);
      --counter
      SELECT COUNT(*) INTO counter
      FROM emp 
      WHERE employee_id
      BETWEEN from_employee AND to_employee;

      --Exceptions
       IF (counter = 0 ) THEN
          RAISE no_element;
       END IF; 

      IF (counter = 1) THEN
          RAISE one_element;
        END IF;

        IF   ascending_order  THEN
          OPEN emp_cur;

          LOOP
              FETCH emp_cur INTO v_id,v_ename,v_surname,v_email,v_telefon,v_hiredate,v_sal,v_job,v_dname,v_manager;
              EXIT WHEN emp_cur%NOTFOUND;
              IF v_id BETWEEN from_employee AND to_employee THEN
          DBMS_OUTPUT.PUT_LINE('Number         : ' || v_id);
          DBMS_OUTPUT.PUT_LINE('Name           : ' || v_ename||' '||v_surname);
          DBMS_OUTPUT.PUT_LINE('Email          : ' || v_email);
          DBMS_OUTPUT.PUT_LINE('Telefon NR.    : ' || v_telefon);
          DBMS_OUTPUT.PUT_LINE('Eingestellt am : ' || v_hiredate);
          DBMS_OUTPUT.PUT_LINE('Gehalt         : ' || v_sal);
          DBMS_OUTPUT.PUT_LINE('Beruf ID       : ' || v_job);
          DBMS_OUTPUT.PUT_LINE('Department     : ' || v_dname);
          DBMS_OUTPUT.PUT_LINE('Vorgesetzter   : ' || v_manager);
           END IF;
          END LOOP;

          CLOSE emp_cur;
         END IF;
         IF  NOT ascending_order  THEN
          OPEN emp_cur_desc;

          LOOP
              FETCH emp_cur_desc INTO v_id,v_ename,v_surname,v_email,v_telefon,v_hiredate,v_sal,v_job,v_dname,v_manager;
              EXIT WHEN emp_cur_desc%NOTFOUND;
              IF v_id BETWEEN from_employee AND to_employee THEN
          DBMS_OUTPUT.PUT_LINE('Number         : ' || v_id);
          DBMS_OUTPUT.PUT_LINE('Name           : ' || v_ename||' '||v_surname);
          DBMS_OUTPUT.PUT_LINE('Email          : ' || v_email);
          DBMS_OUTPUT.PUT_LINE('Telefon NR.    : ' || v_telefon);
          DBMS_OUTPUT.PUT_LINE('Eingestellt am : ' || v_hiredate);
          DBMS_OUTPUT.PUT_LINE('Gehalt         : ' || v_sal);
          DBMS_OUTPUT.PUT_LINE('Beruf ID       : ' || v_job);
          DBMS_OUTPUT.PUT_LINE('Department     : ' || v_dname);
          DBMS_OUTPUT.PUT_LINE('Vorgesetzter   : ' || v_manager);
           END IF;
          END LOOP;

          CLOSE emp_cur_desc;
         END IF;

         EXCEPTION 
        WHEN one_element THEN 
          DBMS_OUTPUT.PUT_LINE('Just one employee was selected');
        WHEN no_element THEN 
          DBMS_OUTPUT.PUT_LINE('No employees were selected');

      END;
      /
      EXECUTE output_employee_set(208,209,FALSE);