03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. ·...

31
오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 1 www.muhanedu.net SQL Cursor SQL 커서 소개 오라클 서버에서는 SQL 문을 실행할 때마다 처리(Parse, Execution)위한 메모리 공간, SQL 커서를 사용하게 된다. 메모리 공간은 Private SQL Area 라고도 불리우며, 오라클의 작업환경이 Dedicated Server 환경이냐 또는 MTS(Multi- Threaded Server)환경이냐에 따라 서버내에 위치되는 곳이 다르다. PL/SQL 블록이 실행될 때에도 내부에 포함된 SQL 문장에 대해 SQL 커서가 자동 적으로 생성되며, 필요에 따라서는 SQL 커서를 사용자가 선언하여 사용할 수도 . SQL 커서의 유형에는 크게 묵시적 커서(Implicit Cursor)명시적 커서(Explicit Cursor)나누어진다. 묵시적 커서는 오라클이 자동적으로 선언하여 사용한 자동적으로 정리(Clean-up) 해준다. 이에 반하여 명시적 커서는 사용자가 정의한 커서를 선언하여 사용하고, 커서의 사용이 끝난 후에는 별도의 정리(Clean-up) 업을 수행해줘야 한다. SQL 커서를 사용할 , 커서는 임의의 커서 상수 값을 제공하는데, 이를 SQL 커서 속성(Cursor Attribute) 이라고 한다. 커서 속성은 커서의 유형에 따라 조금씩 다른 의미를 지니고 있음에 유의한다. 커서 속성에 대한 자세한 사항은 뒷부분에서 다루기로 한다. 보통 오라클에서는 묵시적(Implicit)’ 이라는 단어의 의미는 자동적이다라는 의미를 내포하고 있으며, 이에 반하여 명시적(Explicit)’ 의미는 수동적이다라는 의미를 내포하고 있다. 단어의 의미는 SQL 커서에서도 마찬가지로 사용되고 있다.

Transcript of 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. ·...

Page 1: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 1 www.muhanedu.net

SQL Cursor

SQL 커서 소개

오라클 서버에서는 SQL문을 실행할 때마다 처리(Parse, Execution)를 위한 메모리

공간, 즉 SQL 커서를 사용하게 된다. 이 메모리 공간은 Private SQL Area 라고도

불리우며, 오라클의 작업환경이 Dedicated Server 환경이냐 또는 MTS(Multi-

Threaded Server)환경이냐에 따라 서버내에 위치되는 곳이 다르다.

PL/SQL 블록이 실행될 때에도 내부에 포함된 SQL 문장에 대해 SQL 커서가 자동

적으로 생성되며, 필요에 따라서는 SQL 커서를 사용자가 선언하여 사용할 수도 있

다.

SQL 커서의 유형에는 크게 묵시적 커서(Implicit Cursor)와 명시적 커서(Explicit

Cursor)로 나누어진다1. 묵시적 커서는 오라클이 자동적으로 선언하여 사용한 후

자동적으로 정리(Clean-up) 해준다. 이에 반하여 명시적 커서는 사용자가 정의한

커서를 선언하여 사용하고, 커서의 사용이 끝난 후에는 별도의 정리(Clean-up) 작

업을 수행해줘야 한다.

SQL 커서를 사용할 때, 커서는 임의의 커서 상수 값을 제공하는데, 이를 SQL 커서

속성(Cursor Attribute) 이라고 한다. 이 커서 속성은 커서의 유형에 따라 조금씩

다른 의미를 지니고 있음에 유의한다. 커서 속성에 대한 자세한 사항은 뒷부분에서

다루기로 한다.

1 보통 오라클에서는 ‘묵시적(Implicit)’ 이라는 단어의 의미는 ‘자동적이다’ 라는 의미를 내포하고 있으며, 이에 반하여 ‘명시적(Explicit)’ 의 의미는 ‘수동적이다’ 라는 의미를 내포하고 있다. 이 두 단어의 의미는 SQL 커서에서도 마찬가지로 사용되고 있다.

Page 2: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 2 www.muhanedu.net

묵시적 커서(Implicit Cursor)

묵시적 커서는 오라클에서 자동적으로 선언해주는 SQL 커서로서, 사용자에게는 투

명하게 제공된다.

기본적으로 PL/SQL 블록내에서의 SELECT 문, DML(INSERT, UPDATE, DELETE) 문이

실행될 때마다 묵시적 커서가 선언된다. 여기에서 주의해야 할 점은 묵시적 커서의

경우 세션내에 단 한 개만이 선언되어 사용되었다가 문장이 종료됨과 동시에 정리

된다는 것이다. 그러므로 동시에 여러 개의 묵시적 커서가 사용되는 것이 아니라는

점이다.

묵시적 커서는 SQL 문의 실행된 결과를 커서 속성(Cursor Attribute)을 통해 제공

하고 있는데, 이는 가장 마지막에 실행된 SQL 문의 결과임에 주의한다. 커서 속성

에는 4 가지가 있는데, 묵시적 커서임을 나타내는 SQL%을 접두어(Prefix)로 사용한

다.

>> 묵시적 커서 속성(Cursor Attribute)

종류 설명

SQL%ROWCOUNT 가장 마지막에 실행된 SQL 문장이 처리한 데이터 행의 총 개수를 가지는 속성변수.

SQL%FOUND 가장 마지막에 실행된 SQL 문장이 처리한 데이터 행이 있을 경우에는 TRUE(참) 진리값을, 처리한 데이터 행이 없을 경우에는 FALSE(거짓) 진리값을 가지는 속성 Boolean변수.

SQL%NOTFOUND 가장 마지막에 실행된 SQL 문장이 처리한 데이터 행이 없을 경우에는 TRUE(참) 진리값을, 처리한 데이터 행이 있을 경우에는 FALSE(거짓) 진리값을 가지는 속성 Boolean변수.

SQL%ISOPEN 현재 묵시적 커서가 메모리에 확보되어 있을 경우에는 TRUE(참) 진리값을, 그렇지 않을 경우에는 FALSE(거짓) 진리값을 가지는 속성 Boolean변수. (단, 묵시적 커서는 문장이 실행 종료됨과 동시에 정리(Clean-up)되므로 이 커서속성은 항상 FALSE(거짓) 진리값을 가지게 됨에 주의한다.)

Page 3: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 3 www.muhanedu.net

* 참고 :

SELECT 문장의 경우, 한 건의 데이터를 검색할 경우 이외에는 오라클 예외사

항(EXCEPTION)이 발생한다. 그러므로, SELECT 문장에 관련된 묵시적 커서의

경우에도 마찬가지로 한 건의 데이터를 처리하는 경우에만 정상적으로 사용

가능하다. 만약, 여러 개의 행이 검색될 경우에 처리를 정상적으로 하고자 한

다면, 명시적 커서(Explicit Cursor)를 사용하면 된다.

> EX:

VARIABLE del_cnt VARCHAR2(50)

DECLARE

V_DNO DEPT.DEPTNO%TYPE := &p_dno ;

BEGIN

DELETE EMP WHERE DEPTNO = V_DNO ;

:del_cnt := SQL%ROWCOUNT || ‘ 건 삭제되었습니다.’ ;

END;

PRINT del_cnt

Page 4: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 4 www.muhanedu.net

명시적 커서(Explicit Cursor)

Introduction

명시적 커서는 필요에 따라 사용자가 선언하여 사용하는 SQL 커서 공간으로, 기본

적으로는 여러 개의 행을 처리하고 할 경우 사용된다. 여러 건을 검색하는

SELECT 문장의 경우 오라클은 예외사항(TOO_MANY_ROWS)을 발생하게 된다. 이

때, 오라클은 사용자가 정의한 명시적 커서 영역에 SELECT 문에 의해 검색된 여러

건의 데이터를 임시적으로 저장하고, 한 건씩 처리할 수 있도록 명시적 커서 기능

을 제공한다.

명시적 커서는 동시에 여러 개가 선언되어 사용될 수 있으며, 묵시적 커서와 마찬

가지로 커서 속성 변수를 제공한다. 하지만, 의미는 묵시적 커서와 약간씩 다르다.

명시적 커서는 여러 개가 선언될 수 있으므로, 커서 속성 변수는 ‘명시적 커서 명

(Cursor Name)%’을 커서 속성 변수의 접두어(Prefix)로 붙여서 사용한다.

>> 명시적 커서 속성(Cursor Attribute)

종류 설명

%ROWCOUNT FETCH 문에 의해 읽혀진 데이터의 총 건수를 가지는 속성변수.

%FOUND FETCH 문이 수행되었을 경우, 읽혀진(Fetch) 행이 있을 경우에는 TRUE(참) 진리값을, 그렇지 않을 경우에는 FALSE(거짓) 진리값을 가지는 속성 Boolean

%NOTFOUND FETCH 문이 수행되었을 경우, 읽혀진(Fetch) 행이 없을 경우에는 TRUE(참) 진리값을, 그렇지 않을 경우에는 FALSE(거짓) 진리값을 가지는 속성 Boolean

%ISOPEN 명시적 커서가 메모리에 확보(선언)되어 있을 경우에는 TRUE(참) 진리값을, 그렇지 않을 경우에는 FALSE(거짓) 진리값을 가지는 속성 Boolean변수.

Page 5: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 5 www.muhanedu.net

Explicit Cursor 처리 단계

명시적 커서를 사용하기 위해서는 필수적으로 수행해야 할 4단계가 있다.

1. 명시적 커서 선언(Declaration)

2. 명시적 커서 열기(Open)

3. 명시적 커서로부터 처리할 데이터 행을 읽어오기(Fetch)

( 명시적 커서에 처리하고자 하는 데이터 행이 있다면, 처리가 완료

될 때까지 계속 읽는다.)

4. 명시적 커서의 데이터 행에 처리가 완료되었다면, 정리(Clean-up)작

업을 하기 위해 명시적 커서를 닫는다.(Close)

Page 6: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 6 www.muhanedu.net

명시적 커서 선언(Declaration)

명시적 커서는 선언부(declare)에 다른 식별자와 마찬가지로 선언되며, 형

식은 아래와 같다. 주의해야 할 점은 명시적 커서가 선언부에 기술되어도

메모리 공간이 확보되는 것이 아니라 단지 정의만 이루어진다는 것이다.

> SYNTAX:

CURSOR cursor_name IS select-statement ;

cursor_name 명시적 커서의 이름으로 유일하게 명명되어야 한

다.

select-statement 기본적으로 명시적 커서는 여러 건을 검색하는

SELECT 문을 처리하기 위한 것이므로 처리하고자

하는 데이터를 검색하는 SELECT 문장을 이 부분에

기술하면 된다. 단, 주의해야 할 사항은 정의를 위

한 SELECT 문이므로 PL/SQL 블록의 SELECT~INTO

절과는 구분해야 한다. 즉, 명시적 커서를 정의할

때의 SELECT문은 INTO절을 가지지 않는다.

> EX:

DECLARE CURSOR emp_cur IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 20;

CURSOR dept_emp IS SELECT D.DNAME, E.ENAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO AND E.ENAME LIKE ‘%A%’ ;

....

BEGIN

....

Page 7: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 7 www.muhanedu.net

명시적 커서 열기(Open)

명시적 커서가 사용되기 위해서는 메모리 공간이 확보되어야 하는데, 바로

커서 열기(Open)를 통해 이루어진다.

커서를 열게 되면, 선언부에서 정의된 커서의 SELECT 문이 실행되면서 해당

데이터들(Active Set)이 명시적 커서 영역에 자리잡게 된다. 즉 SELECT 문

에 의해 메모리 공간 크기가 결정되는 것이다.

이때, 명시적 커서 영역에 자리잡은 데이터의 첫번째 행에 커서 포인터

(pointer)가 위치한다. 바로 이 포인터 위치의 데이터 행을 FETCH 문이 읽

게 된다.

> SYNTAX:

OPEN cursor_name ;

cursor_name 열고자 하는 명시적 커서의 이름으로 선언부에 선

언된 커서명중에 하나이어야 한다.

QUIZ:

명시적 커서가 열릴 때, SELECT 문의 결과 행이 한 건

도 없었다면 정상적으로 명시적 커서가 열리는가 ?

Page 8: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 8 www.muhanedu.net

> EX:

DECLARE

CURSOR emp_cur IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 20;

CURSOR dept_emp IS SELECT D.DNAME, E.ENAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO AND E.ENAME LIKE ‘%A%’ ;

....

BEGIN

OPEN emp_cur ;

OPEN dept_emp ;

....

END;

Page 9: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 9 www.muhanedu.net

명시적 커서로부터 데이터 읽기(Fetch)

명시적 커서의 데이터들(Active Set)로부터 데이터를 한 건씩 읽어오기 위

해서 FETCH 문을 사용한다. 이때 읽게 되는 데이터 행은 포인터(Pointer)에

의해서 지정된다.

FETCH 가 되면 자동적으로 포인터는 다음 행에 위치하게 된다. FETCH 후

데이터가 정상적으로 검색되었는지를 판단하기 위

해 %FOUND, %NOTFOUND 와 같은 커서 속성 변수를 사용한다.

데이터들을 읽어 처리하기 위해서 FETCH문은 반복문과 함께 사용한다.

SELECT~INTO절과 마찬가지로 FETCH문도 INTO절을 갖는다.

> SYNTAX:

FETCH cursor_name INTO variable ;

cursor_name 읽어(Fetch) 오고자 하는 명시적 커서의 이름으로

반드시 open 되어야 한다.

Variable 명시적 커서로부터 읽어온(Fetch) 데이터 행(레코

드)을 PL/SQL 블록내에서 처리하기 위해서는 변수

에 저장해야 한다. 이때 variable 에는 단순변수

또는 복합변수가 올 수 있으며, 기본적으로 선언부

에 선언되어야만 한다. 만약 단순변수를 사용한다

면, 커서에서 정의된 SELECT 리스트의 개수 만큼

선언하고 SELECT 리스트의 위치대로 FETCH 의

INTO 절에 차례대로 기술한다. 만약 복합변수를

사용한다면, 커서 레코드 변수(커서명%ROWTYPE)

를 선언하여 사용한다.

Page 10: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 10 www.muhanedu.net

> EX:

DECLARE

CURSOR emp_cur IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 20;

CURSOR dept_emp IS SELECT D.DNAME, E.ENAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO AND E.ENAME LIKE ‘%A%’ ;

e_cur emp_cur%rowtype ; --커서레코드 변수 v_dname dept.dname%type ; v_ename emp.ename%type ; ....

BEGIN

....

FETCH emp_cur INTO e_cur ;

....

FETCH dept_emp INTO v_dname, v_ename ;

....

END ;

Page 11: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 11 www.muhanedu.net

명시적 커서 닫기(Close)

명시적 커서의 정리(Clean-up)작업을 하는 명령으로, 명시적 커서가 다 사

용된 후에는 반드시 ‘닫기’를 강력히 권고한다. 만약 PL/SQL 블록이 명시적

커서를 닫지 않고 종료한다고 해도 치명적인 오류는 발생하지 않는다. 하지

만, 어느 PL/SQL 블록에서 동일명의 커서가 Open 될 때, 오라클은 예외

(EXCEPTION)를 발생한다.

> SYNTAX:

CLOSE cursor_name ;

cursor_name 닫고자 하는 명시적 커서의 이름으로 Close 된 명

시적 커서는 더 이상 접근될 수 없다. 다시 말해

PL/SQL 블록 내에서 Close 된 커서를 접근하게 되

면 오라클은 예외(INVALID_CURSOR)를 발생하게

된다.

Page 12: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 12 www.muhanedu.net

> EX:

DECLARE

CURSOR emp_cur IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 20;

CURSOR dept_emp IS SELECT D.DNAME, E.ENAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO AND E.ENAME LIKE ‘%A%’ ;

e_cur emp_cur%rowtype ; v_dname dept.dname%type ; v_ename emp.ename%type ; ....

BEGIN .... FETCH emp_cur INTO e_cur ; .... .... FETCH dept_emp INTO v_dname, v_ename ; ....

CLOSE emp_cur ;

CLOSE dept_emp ; ....

END;

Page 13: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 13 www.muhanedu.net

Cursor FOR Loop

PL/SQL 블록은 데이터 트랜잭션을 절차적으로 처리하기 위한 효율적인 방법을 제

공한다. 더불어 여러 건의 데이터를 처리하고자 할 때, 명시적 커서는 필수적인 요

소이다.

앞부분에 설명한 것과 같이 명시적 커서를 처리하기 위해서는 기본적으로 4단계를

수행해야만 가능하다.

이에 오라클은 명시적 커서의 좀 더 편리한 사용을 위해 FOR 반복문과 커서를 결

합한 CURSOR FOR 루프를 제공한다. 이는 묵시적인 커서변수의 선언, 커서 열기,

커서내의 레코드를 자동적으로 읽기, 커서 닫기를 수행한다. 이는 별도의 변수선언,

OPEN, FETCH, CLOSE문을 수행하지 않아도 됨을 의미한다.

FOR문의 반복횟수는 명시적 커서(Active Set)내의 전체 행수와 동일하다.

> SYNTAX:

FOR record_name IN cursor_name LOOP

-- 명시적 커서의 OPEN, FETCH가 자동적으로 수행됨.

statement1 ;

statement2 ;

....

END LOOP ; -- 루프문을 빠져 나갈 때 자동적으로 CLOSE됨.

record_name 이는 커서로부터 FETCH 된 하나의 레코드를 저장하

기 위한 커서 레코드 변수로, 묵시적인 선언이 이루

어진다. 만약 선언부에서 선언된다면,

cursor_name%ROWTYPE 형으로 선언되었을 것이다.

커서변수는 복합변수 record 처럼 사용된다. 레코드

를 구성하는 필드를 접근할 때는 레코드변수명을 접

두어로 사용한다.

cursor_name 처리하고자 하는 명시적 커서명으로, 선언부에서 정

의되어야 한다. FOR 문이 실행되면 IN 다음에 기술

Page 14: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 14 www.muhanedu.net

된 명시적 커서가 자동적으로 열어지며, 한 건씩

FETCH 가 되며, 커서 영역에 데이터가 모두 처리되

면 루프를 종료하게 되는데 이때 자동적으로 명시적

커서는 CLOSE 된다.

> EX:

DECLARE

CURSOR emp_cur IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 20;

-- e_cur emp_cur%rowtype ; 선언될 필요가 없다. ....

BEGIN .... FOR e_cur IN emp_cur LOOP

IF e_cur.SAL >= 50000 THEN

....

END LOOP ; ....

END;

QUIZ:

만약 FOR 루프 안에서 COMMIT 문을 수행하게 된다면 어떤 결과가 생

기는가?

Page 15: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 15 www.muhanedu.net

파라미터 Explicit Cursor

명시적 커서를 사용할 때, 정적인 데이터들(Active Set)을 사용할 수도 있지만, 필

요에 따라서는 동적인 데이터들을 처리해야 할 경우도 있다. 이 때 사용되는 것이

파라미터를 가진 명시적 커서이다. 파라미터를 통해 명시적 커서가 열려질 때마다

다른 데이터들(Active Set)을 처리하도록 할 수 있다. 파라미터를 가진 명시적 커

서를 오픈할 때에는 파라미터에 값을 전달해야 한다.

> SYNTAX:

CURSOR cursor_name

[ (parameter_name datatype, …) ] IS select-statement ;

parameter_name 파라미터 변수명으로 변수선언과 동일하다. 여

러 개의 파라미터를 지정할 수 있다.

> EX:

DECLARE CURSOR emp_cur (p_dno emp.deptno%type)) IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = p_dno;

.... BEGIN .... OPEN emp_cur(20) ; .... CLOSE emp_cur ; OPEN emp_cur(30) ; .... CLOSE emp_cur ; ....

END;

Page 16: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 16 www.muhanedu.net

Explicit Cursor 와 FOR UPDATE

명시적 커서 영역에 있는 행들에 대해 잠금(LOCK)이 필요한 경우, 커서를 정의할

때 SELECT ~ FOR UPDATE; 를 사용한다. 만약 다른 세션에서 동일한 행에 대한 잠

금이 설정된 경우, 대기(Waiting)를 방지하기 위해 커서 정의시 NO WAIT 옵션을

사용할 수도 있다.

만약 FOR UPDATE절을 사용하여 명시적 커서가 선언되었다면, 그 커서에 UPDATE

또는 DELETE 하고자 한다면, 문장 끝에 WHERE CURRENT OF 커서명 을 붙여서 접

근한다.

> EX:

DECLARE

CURSOR emp_cur IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 20 FOR UPDATE NO WAIT ;

....

BEGIN ....

OPEN emp_cur ;

....

UPDATE emp

SET sal = sal * 2

WHERE CURRENT OF emp_cur

....

CLOSE emp_cur ; ....

END;

* 참고적으로 커서를 정의할 때, 부질의(Subquery)를 포함한 SELECT 문으로도 가

능하다.

Page 17: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 17 www.muhanedu.net

실습 – SQL CURSOR

1. 부서코드를 입력 받아 해당 부서에 속한 사원들을 삭제한 후 삭제된 사원 건수를 출력하는

PL/SQL 블록.

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

V_DNO NUMBER(7,2) := &p_dno ;

BEGIN

DELETE EMP WHERE DEPTNO = V_DNO ;

DBMS_OUTPUT.PUT_LINE ( ‘삭제된 건수는 ’ || SQL%ROWCOUNT ) ;

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

QUIZ:

만약 해당 부서에 속한 사원이 없었을 경우 위의 PL/SQL 블록은 실패인가 ?

위의 PL/SQL 블록의 출력 조건을

- 해당 부서에 속한 사원이 없다면 ‘소속 사원이 없습니다.’ 라는 메시지를,

- 그 반대의 경우라면 삭제된 건수를

출력하도록 변경 한다면, 위의 실행부는 어떻게 수정해야 하는가 ?

Page 18: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 18 www.muhanedu.net

2. 부서코드를 입력 받아 그 부서에 속한 사원들의 이름, 급여, 직급을 출력하는 PL/SQL 블록.

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

CURSOR emp_cur IS

SELECT ENAME, SAL, JOB

FROM EMP

WHERE DEPTNO = &p_dno ;

V_ENAME EMP.ENAME%TYPE ;

V_SAL EMP.SAL%TYPE ;

V_JOB EMP.JOB%TYPE ;

BEGIN

OPEN emp_cur ;

LOOP

FETCH emp_cur INTO V_ENAME, V_SAL, V_JOB ;

EXIT WHEN emp_cur%NOTFOUND ;

DBMS_OUTPUT.PUT_LINE((RPAD(V_ENAME,16)|| RPAD(V_SAL,10)||V_JOB)) ;

END LOOP ;

CLOSE emp_cur ;

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

Page 19: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 19 www.muhanedu.net

QUIZ:

위의 PL/SQL 블록에서 명시적 커서를 처리할 때, FETCH~INTO 절에 단순변수

가 아닌 복합변수(record)를 사용한다면 위의 블록은 어떻게 수정해야 하는가 ?

(단, 레코드변수의 이름은 emp_rec 으로 한다.)

Page 20: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 20 www.muhanedu.net

3. 2번의 PL/SQL 블록의 실행부를 WHILE문을 수정하여 재작성하시오.

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

CURSOR emp_cur IS

SELECT ENAME, SAL, JOB

FROM EMP

WHERE DEPTNO = &p_dno ;

V_ENAME EMP.ENAME%TYPE ;

V_SAL EMP.SAL%TYPE ;

V_JOB EMP.JOB%TYPE ;

BEGIN

OPEN emp_cur ;

/* 변경할 부분 */

CLOSE emp_cur ;

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

Page 21: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 21 www.muhanedu.net

QUIZ:

위의 PL/SQL 블록에서 명시적 커서를 처리할 때, FETCH~INTO 절에 단순변수

가 아닌 복합변수(record)를 사용한다면 위의 블록은 어떻게 수정해야 하는가 ?

(단, 커서레코드변수의 이름은 emp_rec 으로 한다.)

Page 22: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 22 www.muhanedu.net

4. 2번의 PL/SQL 블록을 CURSOR FOR문으로 수정하시오.

(단, 커서레코드변수의 이름은 EMP_REC으로 한다.)

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

CURSOR emp_cur IS

SELECT ENAME, SAL, JOB

FROM EMP

WHERE DEPTNO = &p_dno ;

BEGIN

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

Page 23: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 23 www.muhanedu.net

QUIZ:

FOR 루프 밖에서 커서 속성 emp_cur%notfound 변수를 사용할 수 있는가?

Page 24: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 24 www.muhanedu.net

5. 제시된 출력결과에 맞도록 아래의 PL/SQL 블록을 완성하시오.

(단, 명시적 커서는 아래에 정의된 dept_cur 와 emp_cur 커서만을 사용하며, BASIC LOOP

문을 사용한다.)

[ 출력 결과 ]

부서코드 : 10 부서명 : XXXXXXXX

ENAME SAL JOB

XXXX $30,000 MANAGER

XXXXX $2,500 SALES

… … …

부서코드 : 20 부서명 : XXXXXXXX

ENAME SAL JOB

XXX … …

XXXXX … …

… … …

Page 25: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 25 www.muhanedu.net

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

CURSOR dept_cur IS

SELECT DEPTNO, DNAME

FROM DEPT

ORDER BY 1 ;

CURSOR emp_cur ( p_dno NUMBER) IS

SELECT ENAME, SAL, JOB

FROM EMP

WHERE DEPTNO = p_dno ;

BEGIN

Page 26: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 26 www.muhanedu.net

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

Page 27: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 27 www.muhanedu.net

6. 5번의 PL/SQL 블록을 다중 CURSOR FOR문으로 수정하시오.

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

CURSOR dept_cur IS SELECT DEPTNO, DNAME FROM DEPT ORDER BY 1 ;

CURSOR emp_cur ( p_dno NUMBER) IS SELECT ENAME, SAL, JOB FROM EMP WHERE DEPTNO = p_dno ;

BEGIN

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

Page 28: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 28 www.muhanedu.net

7. 사원의 급여를 히스토가로막대로 표현하고자 하는 PL/SQL블록.

(단, 급여를 100 단위로 분리하여 100 마다 ‘@’문자로 나타내기로 하며, 결과를 새로 추가한

HISTO 컬럼에도 저장한다.)

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

CURSOR emp_cur IS

SELECT EMPNO, NVL(ROUND(SAL/100),0) CNT

FROM EMP ;

V_HISTO VARCHAR2(50) := NULL ;

BEGIN

FOR emp_rec IN emp_cur LOOP

FOR i IN 1.. emp_rec.CNT LOOP

V_HISTO := V_HISTO || ‘@’ ;

END LOOP ;

UPDATE EMP

SET HISTO = V_HISTO

WHERE EMPNO = emp_rec.EMPNO ;

V_HISTO := NULL ;

END LOOP ;

COMMIT ;

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

Page 29: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 29 www.muhanedu.net

HINT :

HISTO 컬럼을 추가하는 명령

> ALTER TABLE EMP

ADD (HISTO VARCHAR2(50)) ;

SELECT문을 사용하여 HISTO컬럼에 데이터가 저장되었는지 확인해보자.

Page 30: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 30 www.muhanedu.net

8. 7 번의 PL/SQL 블록이 실행되는 동안, 다른 세션에서 EMP 테이블의 데이터를 변경할 수 없도

록 PL/SQL블록을 수정해 보시오.

SET ECHO OFF

SET VERIFY OFF

SET SERVEROUTPUT ON

DECLARE

CURSOR emp_cur IS

SELECT EMPNO, NVL(ROUND(SAL/100),0) CNT

FROM EMP ;

V_HISTO VARCHAR2(50) := NULL ;

BEGIN

FOR emp_rec IN emp_cur LOOP

FOR i IN 1.. emp_rec.CNT LOOP

V_HISTO := V_HISTO || ‘@’ ;

END LOOP ;

UPDATE EMP

SET HISTO = V_HISTO

WHERE EMPNO = emp_rec.EMPNO ;

V_HISTO := NULL ;

END LOOP ;

COMMIT ;

END ;

/

SET SERVEROUTPUT OFF

SET VERIFY OFF

SET ECHO ON

Page 31: 03 SQL CURSOR - Duksungie.duksung.ac.kr/.../reference/03_SQL_CURSOR.pdf · 2004. 4. 13. · 오라클 PL/SQL 3. SQL Cursor Written by AngelaLEE 3 - 2 묵시적 커서(Implicit Cursor)

오라클 PL/SQL 3. SQL Cursor

Written by AngelaLEE 3 - 31 www.muhanedu.net

HINT :

명시적 커서의 SELECT 문에 잠금이 되도록 수정한다.

잠금이 수행된 명시적 커서에 접근할 때에 사용되는 절을 추가하여 변경한다.