编写一个函数来显示基于 Oracle 中特定部门的员工信息?

Writing a function to display employee information based on a particular department in Oracle?

这些是我创建并为创建的表插入值的表的列表:

CREATE TABLE DEPARTMENT
(DEPARTMENT_ID NUMBER PRIMARY KEY,
 DEPARTMENT_NAME VARCHAR(30) NOT NULL
 );

 CREATE TABLE JOBS
 (JOB_ID NUMBER PRIMARY KEY,
  JOB_TITLE VARCHAR(35) NOT NULL,
  MIN_SALARY DECIMAL NOT NULL,
  MAX_SALARY DECIMAL NOT NULL
  );

 CREATE TABLE EMPLOYEES
(EMPLOYEE_ID NUMBER PRIMARY KEY,
 FIRST_NAME VARCHAR(20) NOT NULL,
 LAST_NAME VARCHAR(25) NOT NULL,
 EMAIL VARCHAR(25) NOT NULL,
 PHONE_NUMBER VARCHAR(20) NOT NULL,
 HIRE_DATE DATE NOT NULL,
 JOB_ID NUMBER NOT NULL,
 SALARY DECIMAL NOT NULL,
 DEPARTMENT_ID NUMBER NOT NULL,
 CONSTRAINT emp_job_fk FOREIGN KEY(JOB_ID) REFERENCES JOBS(JOB_ID),
 CONSTRAINT emp_department_fk FOREIGN KEY(DEPARTMENT_ID) REFERENCES DEPARTMENT(DEPARTMENT_ID)
 );

INSERT INTO DEPARTMENT (DEPARTMENT_ID,DEPARTMENT_NAME)
VALUES(1,'IT');
INSERT INTO DEPARTMENT (DEPARTMENT_ID,DEPARTMENT_NAME)
VALUES(2,'Sales');

INSERT INTO JOBS (JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY)
VALUES (1,'IT Administrator',250000.00,50000.00);
INSERT INTO JOBS (JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY)
VALUES (2,'Salesman',200000.00,40000.00);

INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,DEPARTMENT_ID)
VALUES (1,'Tony','Starc','starc@gmail.com','0123456789',TO_DATE('15/1/2008','DD/MM/YYYY'),1,45000.00,1);
INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,DEPARTMENT_ID)
VALUES (2,'Bruce','Wayne','bruce@gmail.com','0123456788',TO_DATE('15/1/2009','DD/MM/YYYY'),1,40000.00,1);
INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,DEPARTMENT_ID)
VALUES (3,'Larry','Ellison','larry@gmail.com','0123456787',TO_DATE('15/1/2010','DD/MM/YYYY'),1,30000.00,1);
INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,DEPARTMENT_ID)
VALUES (4,'Steve','Jobs','steve@gmail.com','0123456786',TO_DATE('15/1/2011','DD/MM/YYYY'),2,35000.00,2);
INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,DEPARTMENT_ID)
VALUES (5,'Remy','Lebeau','remy@gmail.com','0123456785',TO_DATE('15/1/2012','DD/MM/YYYY'),2,30000.00,2);
INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,PHONE_NUMBER,HIRE_DATE,JOB_ID,SALARY,DEPARTMENT_ID)
VALUES (6,'Clark','Kent','clark@gmail.com','0123456784',TO_DATE('15/1/2013','DD/MM/YYYY'),2,20000.00,2);

现在在我的作业中,我被要求解决以下问题:

编写一个名为 fn_emps_per_dept_jc450912 的函数来检索 EMPLOYEE_ID、FIRST_NAME、LAST_NAME AND JOB_TITLE 和 [=46] =].此函数应将 DEPARTMENT_ID 作为输入参数,并且此函数应将 EMPLOYEE_ID、FIRST_NAME、LAST_NAME 和 JOB_TITLE 作为输出参数。它应该 return 如果找到则为真,如果没有找到则为假。

为了显示某个部门的员工信息,我写了如下函数:

CREATE OR REPLACE FUNCTION fn_emps_per_dept_jc450912 (f_dept_id NUMBER)
RETURN SYS_REFCURSOR 
AS
emp_details SYS_REFCURSOR;
BEGIN
OPEN emp_details 
FOR
SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_TITLE
FROM EMPLOYEES,JOBS,DEPARTMENT
WHERE DEPARTMENT.DEPARTMENT_ID = EMPLOYEES.DEPARTMENT_ID
AND JOBS.JOB_ID = EMPLOYEES.JOB_ID
AND EMPLOYEES.DEPARTMENT_ID = f_dept_id;
RETURN emp_details;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Department not available');
END fn_emps_per_dept_jc450912;

VARIABLE e REFCURSOR
EXECUTE :e := fn_emps_per_dept_jc450912(1); 

PRINT e;

EMPLOYEE_ID FIRST_NAME           LAST_NAME                 JOB_TITLE
----------- -------------------- ------------------------- ----------------------------
          1 Tony                 Starc                     IT Administrator
          2 Bruce                Wayne                     IT Administrator
          3 Larry                Ellison                   IT Administrator

然后我尝试插入一个无效的部门编号:

VARIABLE e REFCURSOR
EXECUTE :e := fn_emps_per_dept_jc450912(5); 

PRINT e;

我有以下3个问题:

  1. 为什么是空白的?可能的错误在哪里?
  2. 题目要求输出参数EMPLOYEE_ID,FIRST_NAME,LAST_NAME AND JOB_TITLE。但是我 returning EMPLOYEE_ID,FIRST_NAME,LAST_NAME 和 JOB_TITLE 作为 SYS_REFCURSOR。那么,根据关于输出参数的问题,我的方法是否正确?
  3. 我需要修改代码的哪一部分?如何重写此函数?

NO_DATA_FOUND 不会在打开 REF CURSOR 时引发。所以,你可以使用下面的方法。

  • 将 department_id 的员工人数存储到一个变量中。 如果 count of employees = 0 ,明确提出 NO_DATA_FOUND
  • 在异常块中,打开另一个游标,returns 你 消息而不是原始列。

这里是修改后的函数。

CREATE OR REPLACE FUNCTION fn_emps_per_dept_jc450912(
    f_dept_id NUMBER)
  RETURN SYS_REFCURSOR
AS
  emp_details SYS_REFCURSOR;
  v_emp_id_count NUMBER;
BEGIN
  SELECT COUNT(EMPLOYEES.employee_id)
  INTO v_emp_id_count
  FROM EMPLOYEES,
    JOBS,
    DEPARTMENT
  WHERE DEPARTMENT.DEPARTMENT_ID = EMPLOYEES.DEPARTMENT_ID
  AND JOBS.JOB_ID                = EMPLOYEES.JOB_ID
  AND EMPLOYEES.DEPARTMENT_ID    = f_dept_id;
  IF v_emp_id_count                = 0 THEN
    RAISE NO_DATA_FOUND;
  END IF;
  OPEN emp_details FOR SELECT EMPLOYEE_ID,
  FIRST_NAME,
  LAST_NAME,
  JOB_TITLE FROM EMPLOYEES,
  JOBS,
  DEPARTMENT WHERE DEPARTMENT.DEPARTMENT_ID = EMPLOYEES.DEPARTMENT_ID 
  AND JOBS.JOB_ID = EMPLOYEES.JOB_ID AND EMPLOYEES.DEPARTMENT_ID = f_dept_id;
  RETURN emp_details;
EXCEPTION
WHEN NO_DATA_FOUND THEN
  OPEN emp_details FOR SELECT 'Department not available' MESSAGE FROM DUAL;
  RETURN emp_details;
END fn_emps_per_dept_jc450912;
/

所以对于第二种情况 (dept_id = 5),PRINT 的输出将是。

MESSAGE                  
------------------------ 
Department not available