PL/SQL 에서 SELECT 되어져 나오는 행의 개수가 2개 이상인 경우CURSOR 를 사용하여 나타낼 수도 있다.
table 타입의 변수를 사용하는 것 보다 CURSOR 를 사용하는 것이 더 편하므로
대부분 CURSOR 를 많이 사용한다.
----- *** 명시적 CURSOR 만들기 *** -----
※ 형식
1.단계 -- CURSOR 의 선언(정의)
CURSOR 커서명
IS
SELECT 문;
2.단계 -- CURSOR 의 OPEN
OPEN 커서명;
3.단계 -- CURSOR 의 FETCH
(FETCH 란? SELECT 되어진 결과물을 끄집어 내는 작업을 말한다)
FETCH 커서명 INTO 변수;
4.단계 -- CURSOR 의 CLOSE
CLOSE 커서명;
create or replace procedure 프로시저 이름 ( 매개변수(타입선언))
is
CURSOR 커서명
IS
SELECT 문;
begin
OPEN 커서명;
FETCH 커서명
INTO 변수;
CLOSE 커서명;
--닫히고 나서 if문 선언 등 작성 가능--
end 프로시저명;
※ ==== 커서의 속성변수 ==== ※
1. 커서명%ISOPEN ==> 커서가 OPEN 되어진 상태인가를 체크하는 것.
만약에 커서가 OPEN 되어진 상태이라면 TRUE.
2. 커서명%FOUND ==> FETCH 된 레코드(행)이 있는지 체크하는 것.
만약에 FETCH 된 레코드(행)이 있으면 TRUE.
3. 커서명%NOTFOUND ==> FETCH 된 레코드(행)이 없는지 체크하는 것.
만약에 FETCH 된 레코드(행)이 없으면 TRUE.
4. 커서명%ROWCOUNT ==> 현재까지 FETCH 된 레코드(행)의 갯수를 반환해줌.
create or replace procedure pcd_employees_deptid_cursor
(p_department_id IN employees.department_id%type)
is
cursor cur_empinfo -- 1.단계 ==> CURSOR 의 선언(정의)
is
with E as
(
select department_id
, employee_id
, first_name || ' ' || last_name AS ENAME
, to_char(hire_date, 'yyyy-mm-dd') AS HIREDATE
, func_gender(jubun) AS GENDER
, func_age(jubun) AS AGE
from employees
where department_id = p_department_id-- pk/unique가 아니기 때문에 복수 행수가 나온다. (유일한 값이 아니기 때문) -> 이걸 커서를 사용해서 나타냄
)
select E.department_id, D.department_name, E.employee_id, E.ename, E.hiredate, E.gender, E.age
from departments D right join E
on D.department_id = E.department_id;
v_department_id employees.department_id%type;
v_department_name departments.department_name%type;
v_employee_id employees.employee_id%type;
v_ename varchar2(30);
v_hiredate varchar2(10);
v_gender varchar2(6);
v_age number(3);
v_fetch_count number := 0; -- fetch_count 선언
begin
-- 2.단계 ==> CURSOR 의 OPEN
open cur_empinfo;
-- 3.단계 ==> CURSOR 의 FETCH
-- (FETCH 란? SELECT 되어진 결과물을 끄집어 내는 작업을 말한다)
loop
FETCH cur_empinfo -- cur_empinfo의 한 행을 끄집어내어서 변수에 담는다.
INTO v_department_id, v_department_name, v_employee_id, v_ename, v_hiredate, v_gender, v_age;
EXIT WHEN cur_empinfo%NOTFOUND; -- 더 이상 FETCH 되어진 행이 없다면 반복문을 빠져나간다.!! 있다면 계속 반복한다.
v_fetch_count := cur_empinfo%ROWCOUNT; -- 현재까지 FETCH 된 레코드(행)의 갯수를 반환해줌.
if (v_fetch_count = 1) then
dbms_output.put_line( lpad('-',60,'-') );
dbms_output.put_line( '부서번호 부서명 사원번호 사원명 입사일자 성별 나이' );
dbms_output.put_line( lpad('-',60,'-') );
end if;
dbms_output.put_line(v_department_id || ' ' ||
v_department_name || ' ' ||
v_employee_id || ' ' ||
v_ename || ' ' ||
v_hiredate || ' ' ||
v_gender || ' ' ||
v_age);
-- fatch되어진 행들을 반복문을 돌면서 계속 출력한다.
end loop;
-- 4.단계 ==> CURSOR 의 CLOSE
close cur_empinfo;
if(v_fetch_count = 0) then -- v_fetch_count := cur_empinfo%ROWCOUNT; 이므로, 0일 경우 해당 행이 없다.
dbms_output.put_line('>> 부서번호 ' || p_department_id || '은 존재하지 않습니다. <<' );
else
dbms_output.put_line(' ');
dbms_output.put_line('>> 조회된 행의 개수 : ' || v_fetch_count || '개 <<');
end if;
end pcd_employees_deptid_cursor;
-- Procedure PCD_EMPLOYEES_DEPTID_CURSOR이(가) 컴파일되었습니다.
exec pcd_employees_deptid_cursor(10);
-- PL/SQL 프로시저가 성공적으로 완료되었습니다.
/*
------------------------------------------------------------
부서번호 부서명 사원번호 사원명 입사일자 성별 나이
------------------------------------------------------------
10 Administration 200 Jennifer Whalen 2003-09-17 여 45
>> 조회된 행의 개수 : 1개 <<
*/
exec pcd_employees_deptid_cursor(30);
-- PL/SQL 프로시저가 성공적으로 완료되었습니다.
/*
------------------------------------------------------------
부서번호 부서명 사원번호 사원명 입사일자 성별 나이
------------------------------------------------------------
30 Purchasing 114 Den Raphaely 2002-12-07 여 56
30 Purchasing 115 Alexander Khoo 2003-05-18 남 62
30 Purchasing 116 Shelli Baida 2005-12-24 남 61
30 Purchasing 117 Sigal Tobias 2005-07-24 여 62
30 Purchasing 118 Guy Himuro 2006-11-15 남 45
30 Purchasing 119 Karen Colmenares 2007-08-10 남 44
>> 조회된 행의 개수 : 6개 <<
*/
exec pcd_employees_deptid_cursor(8888);
-- PL/SQL 프로시저가 성공적으로 완료되었습니다.
-- >> 부서번호 8888은 존재하지 않습니다. <<
커서 for문은 이쪽에 작성해두었습니다
https://velog.io/@nime0110/%EC%98%A4%EB%9D%BC%ED%81%B4-for%EB%AC%B8