본문 바로가기

Database

14. PL/SQL - 커서

커서

1. 커서

- 일반 프로그래밍 언어의 파일처리와 방법이 비슷, 행의 집합을 다룰 때 많은 편리한 기능 제공

- 테이블에서 여러 행을 SELECT한 후 쿼리 결과인 행의 집합을 한 행씩 처리하기 위함.

2 . 커서작동순서

- 커서 선언 → 커서 열기 → ( 커서 데이터 가져오기 → 데이터 처리 ) → 커서 닫기

                                                ㄴ LOOP문으로 가져올 행이 없을 때까지 반복

 * 파일처리순서: 파일 open → 처음 데이터 읽음 → 파일의 끝(EOF: End Of File)까지 반복 → 파일 close

 

3. 형식

DECLARE
  CURSOR  커서이름  IS 실행문(select sql문);  -- 커서 선언
BEGIN
  OPEN  커서이름;                    -- 커서 열기
  FETCH  커서이름  INTO  변수이름;   -- 커서로부터 데이터를 읽어와 변수에 저장 
  CLOSE  커서이름                    -- 커서 닫기
END;

* FETCH문

- 셋에서 행 단위로 데이터를 읽음. 각 FETCH 후 CURSOR는 결과셋에서 다음 행으로 이동

- 현재 행에 대한 정보를 얻어 와 INTO 뒤에 기술한 변수에 저장한 후 다음 행으로 이동.

- 얻어진 여러 행에 대한 결과값을 모두 처리하려면 반복문에 FETCH 기술

 

 

4. 커서의 속성

속성
의미
%NOTFOUND
커서 영역의 자료가 모두 FETCH 되었다면 true
%FOUND
커서 영역에 FETCH 되지 않은 자료가 있다면 true
%ISOPEN
커서가 OPEN된 상태이면 true
%ROWCOUNT
커서가 얻어 온 레코드의 개수

명시적 커서와 묵시적 커서

1. 명시적 커서

- 사용자가 직접 정의해서 사용하는 커서로 여러개의 행을 처리할 수 있다.

- 명시적 커서 선언 → 명시적 커서 오픈 → 커서에서 데이터 추출 → 커서 사용 종료

2. 묵시적 커서

- 오라클 내부에서 자동 생성되어 사용하는 커서, PL/SQL 블록에서 실행하는 문장이 실행될 때마다 자동으로 만들어져 사용.

- 커서 속성을 통해 해당 커서에 대한 정보를 얻을 수 있다.(사용자는 생성 유무는 알 수 없다.)

- 묵시적 커서에 저장되는 데이터는 1행만 가능하다.

- OPEN, FETCH, CLOSE 지정 없음

 

 

%TYPE / %ROWTYPE

1. %TYPE

- 해당 변수명은 지정한 테이블 컬럼의 데이터타입, 크기를 따라감(이미 선언된 다른 변수나 컬럼의 데이터 타입 이용하여 선언)

- 기술한 컬럼의 데이터 타입을 모를 경우 사용할 수 있고, 코딩 이후 컬럼 데이터타입이 변경되어도 수정 필요X

2. %ROWTYPE:

- 하나 이상의 데이터 값을 갖는 데이터 타입으로 배열과 비슷한 역할을 하며 재사용 가능

- 테이블, 뷰 내부 컬럼 데이터형, 크기, 속성 등을 그대로 사용 가능

- 지정된 테이블의 구조와 동일한 구조 갖는 변수 선언 가능

- 컬럼들의 수나 데이터 타입을 모를 때 쓸 수 있어 편리

- 데이블의 데이터 컬럼의 데이터타입이 변경될 경우 프로그램 재수정 필요 없음

▶ 차이점

%TYPE은 특정 한 컬럼의 한 개의 데이터만 저장하고

%ROWTYPE은 테이블의 행 단위이기 때문에 모든 컬럼에 대한 값을 저장할 수 있으나 한 번에 한 개의 데이터만 저장

%ROWTYPE

 

예제1: 커서를 사용하여 부서 테이블의 모든 내용을 출력1 (LOOP반복)

DECLARE
 vdept dept_table%ROWTYPE;     -- 변수명 지정: vdept
 CURSOR c1                                               
 IS
 SELECT deptno, dname, loc FROM dept_table;     --  c1커서 선언, 실행될 SELECT문 설정​​
BEGIN
 DBMS_OUTPUT.PUT_LINE('부서번호 | 부서명 | 지역명');
 DBMS_OUTPUT.PUT_LINE('------------------------');
 OPEN c1;                       -- 커서 열기           ​        
LOOP 
 FETCH c1 INTO vdept.deptno, vdept.dname, vdept.loc;    -- 커서로부터 데이터를 읽어와 변수에 저장
 EXIT WHEN c1%NOTFOUND;                                 -- 커서 c1에서 더이상 읽어올 데이터가 없다면 LOOP 탈출
 DBMS_OUTPUT.PUT_LINE(vdept.deptno || '  ' || vdept.dname || '  ' || vdept.loc);
END LOOP;
END;

 

예제2: 커서를 사용하여 부서 테이블의 모든 내용을 출력2(FOR문)

DECLARE
 vdept dept_table%ROWTYPE;
 CURSOR c1
 IS 
 SELECT * FROM dept_table;
BEGIN 
 DBMS_OUTPUT.PUT_LINE('부서번호 | 부서명 | 지역명');
 DBMS_OUTPUT.PUT_LINE('------------------------'); 

 FOR vdept IN c1 LOOP
 EXIT WHEN c1%NOTFOUND;
 DBMS_OUTPUT.PUT_LINE(vdept.deptno|| '  ' || vdept.dname ||'  ' ||vdept.loc);
 END LOOP;
END;

 

 

%TYPE

예제1: emp_table에 저장되어 있는 deptno, empno, ename, sal 정보 출력(부서번호 20에 해당하는 행들만 가져오기)

DECLARE
 vdeptno emp_table.deptno%type;
 vempno emp_table.empno%type;
 vename emp_table.ename%type;
 vsal emp_table.sal%type;
 CURSOR c2
 IS
 SELECT deptno, empno, ename, sal FROM emp_table WHERE deptno = 20;
BEGIN
 OPEN ​c2;
 DBMS_OUTPUT.PUT_LINE('부서번호 | 사원번호 | 사원이름 | 급여');
 DBMS_OUTPUT.PUT_LINE('---------------------------------'); 

LOOP 
 FETCH c2 INTO vdeptno, vempno, vename, vsal;
 EXIT WHEN c2%NOTFOUND;
  DBMS_OUTPUT.PUT_LINE(vdeptno || ' ' || vempno || ' ' || vename || ' ' || vsal);
END LOOP;
END;

 

예제2: emp_table에서 job을 입력받아서 deptno, ename, job 출력

DECLARE
 v_deptno emp_table.deptno%type;
 v_ename emp_table.ename%type;
 v_job emp_Table.job%type;
 CURSOR c3
 IS 
 SELECT deptno, ename, job FROM emp_table WHERE job = '&job'; -- 주의 (숫자 &~  / 문자 '&~~')
BEGIN 
 OPEN c3;
 DBMS_OUTPUT.PUT_LINE('부서번호 | 사원이름 | 직무');
 DBMS_OUTPUT.PUT_LINE('---------------------------------');

LOOP 
 FETCH c3 INTO v_deptno, v_ename, v_job;
 EXIT WHEN c3%NOTFOUND;
 DBMS_OUTPUT.PUT_LINE(v_deptno || '  ' || v_ename || '  ' || v_job);
END LOOP;
END;

 

 

'Database' 카테고리의 다른 글

16. SQL응용(JDBC연결하기, 사용하기)  (0) 2023.05.08
15. PL/SQL - 함수/프로시저/트리거  (0) 2023.05.04
13. PL/SQL - 제어문  (0) 2023.05.04
12. PL/SQL - SQL*Plus  (0) 2023.05.04
11. 그룹함수: ROLLUP/CUBE/GROUPING SET  (0) 2023.05.04