레코드 및 커서 사용
이 페이지의 스크립트 콘텐츠는 탐색 용도로만 사용되며 어떤 방식으로든 콘텐츠를 변경하지 않습니다.
데이터 값을 레코드에 저장하고 커서를 결과 집합 및 관련 처리 정보에 대한 포인터로 사용할 수 있습니다.
참조: Oracle Database PL/SQL Language Reference에서 레코드에 대한 자세한 내용을 참조하십시오.
레코드 정보
레코드는 서로 다른 유형의 데이터 값을 저장할 수 있는 PL/SQL 조합 변수입니다. 내부 구성 요소(fields)를 스칼라 변수처럼 처리할 수 있습니다. 전체 레코드를 서브 프로그램 파라미터로 전달할 수 있습니다. 레코드는 테이블 행의 데이터나 테이블 행에 있는 특정 열의 데이터를 보관하는 데 사용할 수 있습니다.
레코드는 여러 유형의 데이터 값을 저장할 수 있는 PL/SQL 조합 변수로, C, C++ 또는 Java의 struct 유형과 유사합니다. 레코드의 내부 구성 요소를 필드라고 합니다. 레코드 필드에 액세스하려면 점 표기법(record_name.field_name)을 사용합니다.
레코드 필드를 스칼라 변수처럼 처리할 수 있습니다. 전체 레코드를 서브 프로그램 파라미터로 전달할 수도 있습니다.
레코드는 테이블 행의 데이터나 테이블 행에 있는 특정 열의 데이터를 보관하는 데 사용할 수 있습니다. 각 레코드 필드는 테이블 열에 해당합니다.
레코드를 생성하는 방법은 세 가지입니다.
-
RECORD 유형을 선언한 다음 해당 유형의 변수를 선언합니다.
다음 구문을 사용합니다.
TYPE record_name IS RECORD ( field_name data_type [:= initial_value] [, field_name data_type [:= initial_value ] ]... ); variable_name record_name; -
table_name%ROWTYPE 유형의 변수를 선언합니다.
레코드의 필드는 테이블의 열과 이름 및 데이터 유형이 동일합니다.
-
cursor_name%ROWTYPE 유형의 변수를 선언합니다.
레코드의 필드는 커서 SELECT 문의 FROM 절에 있는 테이블의 열과 이름 및 데이터 유형이 동일합니다.
참조:
-
Oracle Database PL/SQL Language Reference - RECORD 유형 정의 및 해당 유형의 레코드 선언에 대한 자세한 내용
-
RECORD 유형 정의의 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
%ROWTYPE 속성에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
Oracle Database PL/SQL Language Reference - %ROWTYPE 속성 구문
자습서: RECORD 유형 선언
다음 단계에서는 SQL Developer 툴 편집을 사용하여 sal_info라는 RECORD 유형을 선언하는 방법을 보여줍니다. 이 유형의 필드는 직원의 봉제 정보(작업 ID, 작업 ID에 대한 최소 및 최대 봉제, 현재 봉제 및 제안된 인상)를 보유할 수 있습니다.
RECORD type sal_info를 선언하는 단계
-
Connections(연결) 프레임에서 hr_conn을 확장합니다.
hr_conn 아이콘 아래에 스키마 객체 유형 목록이 나타납니다.
-
패키지를 확장합니다.
패키지 목록이 나타납니다.
-
EMP_EVAL을 마우스 오른쪽 버튼으로 누릅니다.
선택 사항 목록이 나타납니다.
-
편집을 선택합니다.
EMP_EVAL 창이 열리고 이 패키지를 생성한
CREATE PACKAGE문이 표시됩니다.CREATE OR REPLACE PACKAGE EMP_EVAL AS PROCEDURE eval_department(dept_id IN NUMBER); FUNCTION calculate_score(evaluation_id IN NUMBER , performance_id IN NUMBER) RETURN NUMBER; END EMP_EVAL; -
EMP_EVAL 창에서
END EMP_EVAL바로 앞에 다음 코드를 추가합니다.TYPE sal_info IS RECORD ( j_id jobs.job_id%type , sal_min jobs.min_salary%type , sal_max jobs.max_salary%type , sal employees.salary%type , sal_raise NUMBER(3,3) );창의 제목이 기울임꼴로 표시되어 변경 사항이 데이터베이스에 저장되지 않았음을 나타냅니다.
-
컴파일 아이콘을 선택합니다.
변경된 패키지 사양이 컴파일되고 데이터베이스에 저장됩니다. EMP_EVAL 창의 제목은 더 이상 기울임꼴 글꼴로 표시되지 않음
이제 "자습서: 레코드 매개변수로 하위 프로그램 생성 및 호출"에 설명된 대로 sal_info 유형의 레코드를 선언할 수 있습니다.
자습서: 레코드 매개변수를 사용하여 하위 프로그램 생성 및 호출
다음 단계에서는 SQL Developer 툴 Edit를 사용하여 레코드 유형이 sal_info인 서브 프로그램을 생성하고 호출하는 방법을 보여줍니다.
레코드 유형 sal_info은 "자습서: 레코드 유형 선언"에서 생성되었습니다.
이 자습서에서는 SQL Developer 툴 Edit를 사용하여 다음 작업을 완료하는 방법을 보여줍니다.
-
sal_info유형 매개변수를 포함하는 SALARY_SCHEDULE 프로시저를 만듭니다. -
sal_info함수에서 EVAL_FREQUENCY 함수를 선언하고 해당 필드를 채운 다음 SALARY_SCHEDULE 프로시저에 전달하도록 EVAL_FREQUENCY 함수를 변경합니다.
EVAL_FREQUENCY가 SALARY_SCHEDULE을 호출하므로 SALARY_SCHEDULE 선언이 EVAL_FREQUENCY 선언보다 앞에 있어야 합니다. 그렇지 않으면 패키지가 컴파일되지 않습니다. 그러나 SALARY_SCHEDULE 정의는 패키지 본문에서 아무 위치에나 있을 수 있습니다.
SALARY_SCHEDULE을 생성하고 EVAL_FREQUENCY를 변경하는 단계:
-
Connections(연결) 프레임에서 hr_conn을 확장합니다.
-
스키마 객체 유형 목록에서 패키지를 확장합니다.
-
패키지 목록에서 EMP_EVAL을 확장합니다.
-
선택 항목 목록에서 EMP_EVAL 본문을 마우스 오른쪽 버튼으로 누릅니다.
-
선택 항목 목록에서 편집을 선택합니다.
EMP_EVAL Body 창이 나타나고 패키지 본문의 코드가 표시됩니다.
-
EMP_EVAL [본문] 창에서
END EMP_EVAL바로 앞에 SALARY_SCHEDULE 프로시저에 대한 다음 정의를 추가합니다.PROCEDURE salary_schedule (emp IN sal_info) AS accumulating_sal NUMBER; BEGIN DBMS_OUTPUT.PUT_LINE('If salary ' || emp.sal || ' increases by ' || ROUND((emp.sal_raise * 100),0) || '% each year, it will be:'); accumulating_sal := emp.sal; WHILE accumulating_sal <= emp.sal_max LOOP accumulating_sal := accumulating_sal * (1 + emp.sal_raise); DBMS_OUTPUT.PUT_LINE(ROUND(accumulating_sal,2) ||', '); END LOOP; END salary_schedule;창의 제목이 기울임꼴로 표시되어 변경 사항이 데이터베이스에 저장되지 않았음을 나타냅니다.
-
EMP_EVAL Body 창에서 다음 위치에 eval_frequency 함수와 salary_schedule 및 add_eval 프로시저를 입력합니다.
CREATE OR REPLACE PACKAGE BODY EMP_EVAL AS FUNCTION eval_frequency (emp_id EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN PLS_INTEGER; PROCEDURE salary_schedule(emp IN sal_info); PROCEDURE add_eval(employee_id IN employees.employee_id%type, today IN DATE); PROCEDURE eval_department (dept_id IN NUMBER) AS -
EVAL_FREQUENCY함수를 편집하여 다음과 같이 변경합니다.FUNCTION eval_frequency (emp_id EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN PLS_INTEGER AS h_date EMPLOYEES.HIRE_DATE%TYPE; today EMPLOYEES.HIRE_DATE%TYPE; eval_freq PLS_INTEGER; emp_sal SAL_INFO; -- replaces sal, sal_raise, and sal_max BEGIN SELECT SYSDATE INTO today FROM DUAL; SELECT HIRE_DATE INTO h_date FROM EMPLOYEES WHERE EMPLOYEE_ID = eval_frequency.emp_id; IF ((h_date + (INTERVAL '120' MONTH)) < today) THEN eval_freq := 1; /* populate emp_sal */ SELECT j.JOB_ID, j.MIN_SALARY, j.MAX_SALARY, e.SALARY INTO emp_sal.j_id, emp_sal.sal_min, emp_sal.sal_max, emp_sal.sal FROM EMPLOYEES e, JOBS j WHERE e.EMPLOYEE_ID = eval_frequency.emp_id AND j.JOB_ID = eval_frequency.emp_id; emp_sal.sal_raise := 0; -- default CASE emp_sal.j_id WHEN 'PU_CLERK' THEN emp_sal.sal_raise := 0.08; WHEN 'SH_CLERK' THEN emp_sal.sal_raise := 0.07; WHEN 'ST_CLERK' THEN emp_sal.sal_raise := 0.06; WHEN 'HR_REP' THEN emp_sal.sal_raise := 0.05; WHEN 'PR_REP' THEN emp_sal.sal_raise := 0.05; WHEN 'MK_REP' THEN emp_sal.sal_raise := 0.04; ELSE NULL; END CASE; IF (emp_sal.sal_raise != 0) THEN salary_schedule(emp_sal); END IF; ELSE eval_freq := 2; END IF; RETURN eval_freq; END eval_frequency; -
컴파일을 선택합니다.
커서 정보
Oracle Database에서 SQL 문을 실행하면 결과 집합과 처리 정보를 이름이 없는 전용(private) SQL 영역에 저장합니다. 커서라고 하는 이 이름 없는 영역에 대한 포인터를 사용하면 한 번에 한 행씩 결과 집합을 검색할 수 있습니다. 커서 속성은 커서 상태에 대한 정보를 반환합니다.
PL/SQL은 SQL DML 문 또는 PL/SQL SELECT INTO 문을 실행할 때마다 암시적 커서를 엽니다. 이 커서에 대한 정보를 커서의 속성에서 가져올 수 있지만 커서를 제어할 수는 없습니다. 명령문이 실행된 후 데이터베이스에서 커서가 닫지만 커서 속성 값은 다른 DML 또는 SELECT INTO 문을 실행할 때까지 계속 사용할 수 있습니다.
PL/SQL에서는 커서도 선언할 수 있습니다. 선언된 커서는 이름이 있고 대개 여러 행을 반환하는 질의(SQL SELECT 문)와 연결되어 있으며, 커서를 선언한 후에는 암시적 또는 명시적으로 처리해야 합니다. 커서를 암시적으로 처리하려면 커서 FOR LOOP를 사용합니다. 구문은 다음과 같습니다.
FOR record_name IN cursor_name LOOP
statement
[ statement ]...
END LOOP;
커서를 명시적으로 처리하려면 OPEN 문을 사용하여 해당 커서를 열고 결과 집합에서 한 번에 하나씩 또는 대량으로(FETCH 문 사용) 행을 패치한 다음 CLOSE 문으로 커서를 닫습니다. 커서를 닫은 후에는 결과 집합에서 레코드를 인출하거나 커서 속성 값을 볼 수 없습니다.
암시적 커서 속성의 값에 대한 구문은 SQL%attribute입니다(예: SQL%FOUND). SQL%attribute는 항상 가장 최근에 실행된 DML 또는 SELECT INTO 문을 참조합니다.
선언된 커서 속성 값의 구문은 cursor_name%attribute입니다(예: c1%FOUND). 표 1에서는 커서 속성과 해당 속성이 반환할 수 있는 값을 나열합니다. 암시적 커서에는 추가 속성이 있지만 이 설명서에서 다루지 않습니다.
테이블 1 커서 속성 값
| 속성 | 선언된 커서에 대한 값 | 암시적 커서에 대한 값 |
|---|---|---|
| %발견 | 커서가 열려 있지만 인출이 시도되지 않은 경우(각주 1) NULL입니다. 최근 인출에서 행을 반환한 경우 TRUE입니다. 최근 인출에서 행을 반환하지 않은 경우 FALSE입니다. |
DML 또는 SELECT INTO 문이 실행되지 않은 경우 NULL입니다. 최근 DML 또는 SELECT INTO 문에서 행을 반환한 경우 TRUE입니다. 최근 DML 또는 SELECT INTO 문에서 행을 반환하지 않은 경우 FALSE입니다. |
| %찾을 수 없음 | 커서가 열려 있지만 인출이 시도되지 않은 경우(각주 1) NULL입니다. 최근 인출에서 행을 반환한 경우 FALSE입니다. 최근 인출에서 행을 반환하지 않은 경우 TRUE입니다. |
DML 또는 SELECT INTO 문이 실행되지 않은 경우 NULL입니다. 최근 DML 또는 SELECT INTO 문에서 행을 반환한 경우 최근 DML 또는 SELECT INTO 문에서 행을 반환하지 않은 경우 |
| 행 수 % | 커서가 열려 있는 경우(각주 1), 0보다 크거나 동일한 숫자입니다. | DML 또는 SELECT INTO 문이 실행되지 않았으면 NULL이고, 그렇지 않은 경우에는 0보다 크거나 동일한 숫자입니다. |
| %ISOPEN | 커서가 열려 있는 경우 TRUE이고, 열려 있지 않은 경우 FALSE입니다. | 항상 거짓입니다. |
각주 1: 커서가 열려 있지 않으면 속성이 미리 정의된 예외 INVALID_CURSOR를 발생시킵니다.
참조:
-
"질의 정보"
-
SELECT INTO 문에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참조하십시오
-
PL/SQL에서 커서를 관리하는 방법은 Oracle Database PL/SQL Language Reference를 참조하십시오
선언된 커서를 사용하여 한 번에 하나씩 결과 집합 행 가져오기
선언된 커서를 사용하여 결과 집합 행을 한 번에 하나씩 검색할 수 있습니다.
다음 프로시저에서는 필요한 각 명령문을 가장 단순한 형태로 사용하지만 전체 구문에 대한 참조를 제공합니다.
선언된 커서를 사용하여 결과 집합 행을 한 번에 하나씩 검색하는 단계
-
선언 부분에서 다음을 수행합니다.
-
커서를 선언합니다.
CURSOR cursor_name IS query;전체 선언된 커서 선언 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
커서에서 반환한 행을 보관할 레코드를 선언합니다.
record_name cursor_name%ROWTYPE;전체 %ROWTYPE 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
-
실행 부분에서 다음을 수행합니다.
-
커서를 엽니다.
OPEN cursor_name;전체 OPEN 문 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
다음 코드와 유사한 구문의 LOOP 문을 사용하여 커서의 행(결과 집합의 열)을 한 번에 한 행마다 인출합니다.
LOOP FETCH cursor_name INTO record_name; EXIT WHEN cursor_name%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;전체 FETCH 문 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
커서를 닫습니다.
CLOSE cursor_name;
-
전체 CLOSE 문 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
자습서: 선언된 커서를 사용하여 한 번에 하나씩 결과 집합 행 검색을 수행합니다.
다음 단계에서는 선언된 커서 emp_cursor를 사용하는 EMP_EVAL.EVAL_DEPARTMENT 프로시저를 구현하는 방법을 보여줍니다.
EMP_EVAL.EVAL_DEPARTMENT 프로시저를 구현하는 단계는 다음과 같습니다.
-
EMP_EVAL 패키지 사양에서 EVAL_DEPARTMENT 프로시저 선언을 굵게 표시된 대로 변경합니다.
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE); -
EMP_EVAL 패키지 본문에서 다음 예제에 표시된 대로 EVAL_DEPARTMENT 프로시저 정의를 변경합니다.
PROCEDURE eval_department (dept_id IN employees.department_id%TYPE) AS CURSOR emp_cursor IS SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = eval_department.dept_id; emp_record EMPLOYEES%ROWTYPE; -- for row returned by cursor all_evals BOOLEAN; -- true if all employees in dept need evaluations today DATE; BEGIN today := SYSDATE; IF (EXTRACT(MONTH FROM today) < 6) THEN all_evals := FALSE; -- only new employees need evaluations ELSE all_evals := TRUE; -- all employees need evaluations END IF; OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'Determining evaluations necessary in department # ' || dept_id ); LOOP FETCH emp_cursor INTO emp_record; EXIT WHEN emp_cursor%NOTFOUND; IF all_evals THEN add_eval(emp_record.employee_id, today); ELSIF (eval_frequency(emp_record.employee_id) = 2) THEN add_eval(emp_record.employee_id, today); END IF; END LOOP; DBMS_OUTPUT.PUT_LINE('Processed ' || emp_cursor%ROWCOUNT || ' records.'); CLOSE emp_cursor; END eval_department;패키지 본문을 변경하는 단계별 예제는 "자습서: 하위 프로그램에서 변수 및 상수 선언"을 참조하십시오.
-
EMP_EVAL 패키지 사양을 컴파일합니다.
-
EMP_EVAL 패키지 본문을 컴파일합니다.
커서 변수 정보
커서 변수는 하나의 질의로 제한되지 않는다는 점만적으로 커서와 같습니다. 질의의 커서 변수를 열고 결과 집합을 처리한 다음 커서 변수를 다른 질의에 사용할 수 있습니다. 하위 프로그램 간에 질의 결과를 전달하는 데 커서 변수를 사용하면 편리합니다.
커서에 대한 자세한 내용은 "커서 정보"를 참조하십시오.
커서 변수를 선언하려면 REF CURSOR 유형을 선언한 다음 해당 유형의 변수를 선언합니다. 이로 인해 커서 변수를 REF CURSOR라고 하는 경우가 많습니다. REF CURSOR 유형에는 강한 유형이나 약한 유형이 있습니다.
강한 REF CURSOR 유형은 커서 변수의 RECORD 유형인 반환 유형을 지정합니다. PL/SQL 컴파일러에서는 이러한 강력한 입력의 커서 변수를 반품 유형이 아닌 행을 반환하는 질의에 사용할 수 없습니다. 강한 REF CURSOR 유형은 약한 유형 보다 오류를 덜 발생시키지만 약한 유형 보다 융통성이 떨어졌습니다.
약한 REF CURSOR 유형은 반환 유형을 지정하지 않습니다. PL/SQL 컴파일러에서는 약한 유형의 커서 변수를 모든 질의에서 허용합니다. 약한 REF CURSOR 유형은 교환 가능하므로 약한 REF CURSOR 유형을 만들지 말고 미리 정의된 약한 커서 유형 SYS_REFCURSOR를 사용할 수 있습니다.
커서 변수를 선언한 후에는 특정 질의에 대해 커서 변수를 열고(OPEN FOR 문 이용), 결과 집합에서 한 번에 한 행씩 인출한(FETCH 문 이용) 다음 커서를 닫거나(CLOSE 문 이용) 다른 특정 질의에서 열어야(OPEN FOR 문 이용)합니다. 다른 질의에서 커서 변수를 열면 이전 질의에서는 커서 변수가 닫힙니다. 특정 질의에서 커서 변수를 닫은 후에는 해당 질의의 결과 집합에서 레코드를 인출하거나 해당 질의의 커서 특성 값을 볼 수 없습니다.
참조:
-
커서 변수 사용에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
커서 변수 선언 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오
커서 변수를 사용하여 한 번에 하나씩 결과 집합 행 검색
커서 변수를 사용하여 결과 집합 행을 한 번에 한 행씩 검색할 수 있습니다.
다음 프로시저에서는 필요한 각 명령문을 가장 단순한 형태로 사용하지만 전체 구문에 대한 참조를 제공합니다.
커서 변수를 사용하여 결과 집합 행을 한 번에 한 행씩 검색하는 단계:
-
선언 부분에서 다음을 수행합니다.
-
REF CURSOR 유형을 선언합니다.
TYPE cursor_type IS REF CURSOR [ RETURN return_type ];전체 REF CURSOR 유형 선언 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
해당 유형의 커서 변수를 선언합니다.
cursor_variable cursor_type;전체 커서 변수 선언 구문은 Oracle Database PL/SQL Language Reference를 참조하십시오.
-
커서에서 반환한 행을 보관할 레코드를 선언합니다.
record_name return_type;레코드 선언 구문에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 확인하십시오.
-
-
실행 부분에서 다음을 수행합니다.
-
특정 질의에서 커서 변수를 엽니다.
OPEN cursor_variable FOR query;OPEN FOR 문 구문에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참고하세요.
-
다음과 유사한 구문의 LOOP 문을 사용하여 커서 변수의 행(결과 집합의 Row)을 한 번에 한 행마다 인출합니다.
LOOP FETCH cursor_variable INTO record_name; EXIT WHEN cursor_variable%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;FETCH 문 구문에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참고하세요.
-
커서 변수를 닫습니다.
CLOSE cursor_variable;또는 다른 질의에서 커서 변수를 열 수도 있습니다. 그러면 현재 질의에서는 커서 변수가 닫힙니다.
CLOSE 문 구문에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참고하세요.
-
자습서: 커서 변수를 사용하여 한 번에 하나씩 결과 집합 행 검색
다음 단계에서는 선언된 커서(여러 부서를 처리할 수 있음) 대신 커서 변수를 사용하도록 EMP_EVAL.EVAL_DEPARTMENT 프로시저를 변경하는 방법과 EMP_EVAL.EVAL_DEPARTMENT 및 EMP_EVAL.ADD_EVAL을 보다 효율적으로 만드는 방법을 보여줍니다.
또한이 자습서에서는 EMP_EVAL.EVAL_DEPARTMENT 및 EMP_EVAL.ADD_EVAL을 보다 효율적으로 만드는 방법도 보여줍니다. 즉, 레코드의 필드 하나를 ADD_EVAL에 전달하고 ADD_EVAL에서 세 가지 질의를 사용하여 같은 레코드의 다른 세 개의 필드를 추출하게 하는 대신, EVAL_DEPARTMENT에서 전체 레코드를 ADD_EVAL에 전달하고 ADD_EVAL은 점 표기법을 사용하여 다른 세 개의 필드의 값에 액세스합니다.
커서 변수를 사용하도록 EMP_EVAL.EVAL_DEPARTMENT 프로시저를 변경하는 단계는 다음과 같습니다.
-
다음 예제에 표시된 것처럼 EMP_EVAL 패키지 사양에서 프로시저 선언 및 REF CURSOR 유형 정의를 추가합니다.
CREATE OR REPLACE PACKAGE emp_eval AS PROCEDURE eval_department (dept_id IN employees.department_id%TYPE); PROCEDURE eval_everyone; FUNCTION calculate_score(eval_id IN scores.evaluation_id%TYPE , perf_id IN scores.performance_id%TYPE) RETURN NUMBER; TYPE SAL_INFO IS RECORD ( j_id jobs.job_id%type , sal_min jobs.min_salary%type , sal_max jobs.max_salary%type , salary employees.salary%type , sal_raise NUMBER(3,3)); TYPE emp_refcursor_type IS REF CURSOR RETURN employees%ROWTYPE; END emp_eval; -
EMP_EVAL 패키지 본문에서 EVAL_LOOP_CONTROL 프로시저의 정방향 선언을 추가하고 ADD_EVAL 프로시저 선언을 다음과 같이 변경합니다.
CREATE OR REPLACE PACKAGE BODY EMP_EVAL AS FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN PLS_INTEGER; PROCEDURE salary_schedule(emp IN sal_info); PROCEDURE add_eval(emp_record IN EMPLOYEES%ROWTYPE, today IN DATE); PROCEDURE eval_loop_control(emp_cursor IN emp_refcursor_type); ...패키지 본문을 변경하는 단계별 예제는 "자습서: 하위 프로그램에서 변수 및 상수 선언"을 참조하십시오.
-
부서별로 세 개의 개별 결과 집합을 검색하고 다음 예제에 표시된 대로 EVAL_LOOP_CONTROL 프로시저를 호출하도록 EVAL_DEPARTMENT 프로시저를 셸게 표시된 대로 변경합니다
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS emp_cursor emp_refcursor_type; current_dept departments.department_id%TYPE; BEGIN current_dept := dept_id; FOR loop_c IN 1..3 LOOP OPEN emp_cursor FOR SELECT * FROM employees WHERE current_dept = eval_department.dept_id; DBMS_OUTPUT.PUT_LINE ('Determining necessary evaluations in department #' || current_dept); eval_loop_control(emp_cursor); DBMS_OUTPUT.PUT_LINE ('Processed ' || emp_cursor%ROWCOUNT || ' records.'); CLOSE emp_cursor; current_dept := current_dept + 10; END LOOP; END eval_department; -
다음과 같이 ADD_EVAL 프로시저를 변경합니다.
PROCEDURE add_eval(emp_record IN employees%ROWTYPE, today IN DATE) AS -- (Delete local variables) BEGIN INSERT INTO EVALUATIONS ( evaluation_id, employee_id, evaluation_date, job_id, manager_id, department_id, total_score ) VALUES ( evaluations_sequence.NEXTVAL, -- evaluation_id emp_record.employee_id, -- employee_id today, -- evaluation_date emp_record.job_id, -- job_id emp_record.manager_id, -- manager_id emp_record.department_id, -- department_id 0 -- total_score ); END add_eval; -
END EMP_EVAL앞에 결과 집합에서 개별 레코드를 인출하여 처리하는 다음 프로시저를 추가합니다.PROCEDURE eval_loop_control (emp_cursor IN emp_refcursor_type) AS emp_record EMPLOYEES%ROWTYPE; all_evals BOOLEAN; today DATE; BEGIN today := SYSDATE; IF (EXTRACT(MONTH FROM today) < 6) THEN all_evals := FALSE; ELSE all_evals := TRUE; END IF; LOOP FETCH emp_cursor INTO emp_record; EXIT WHEN emp_cursor%NOTFOUND; IF all_evals THEN add_eval(emp_record, today); ELSIF (eval_frequency(emp_record.employee_id) = 2) THEN add_eval(emp_record, today); END IF; END LOOP; END eval_loop_control; -
END EMP_EVAL앞에 회사의 모든 직원이 포함된 결과 집합을 검색하는 다음 프로시저를 추가합니다.PROCEDURE eval_everyone AS emp_cursor emp_refcursor_type; BEGIN OPEN emp_cursor FOR SELECT * FROM employees; DBMS_OUTPUT.PUT_LINE('Determining number of necessary evaluations.'); eval_loop_control(emp_cursor); DBMS_OUTPUT.PUT_LINE('Processed ' || emp_cursor%ROWCOUNT || ' records.'); CLOSE emp_cursor; END eval_everyone; -
EMP_EVAL패키지 사양을 컴파일합니다. -
EMP_EVAL패키지 본문을 컴파일합니다.