기타/정처기

정보처리기사 실기 시나공 8장 SQL 응용

TheWing 2020. 12. 31. 18:04

SQL - DML

그룹함수

  • ROLLUP(속성명, 속성명,—-)
    • 인수로 주어진 속성을 대상으로 그룹별 소계를 하는 함수
    • 속성의 개수가 N개이면, N+1레벨가지, 하위 레벨에서 상위 레벨 순으로 데이터가 집계됩니다.
  • CUBE(속성명, 속성명, - - -)
    • ROLLUP과 유사한 형태이나 CUBE는 인수로 주어진 속성을 대상으로 모든 조합의 그룹별 소계를 구합니다.
    • 속성의 개수가 N개 이면 N2 레벨까지 , 상위 레벨에서 하위 레벨 순으로 데이터가 집계됩니다.

WINDOW 함수

  • ROW_NUMBER()

    • 윈도우 별로 각 레코드에 대한 일련 번호를 반환합니다.
    • RANK()
      • 윈도우별로 순위를 반환하며, 공동 순위를 반영합니다
    • DENSE_RANK()
      • 윈도우별로 순위를 반환하며, 공동 순위를 무시하고 순위를 부여합니다.
  • <상여금> 테이블에서 '상여금'이 100이상인 사원이 2명이상인 '부서'의 튜플의 수를 구하시오

    • SELECT 부서, COUNT() AS 사원수 FROM 상여금 WHERE 상여금 > = 100 GROUP BY 부서 HAVING COUNT() > =2;
  • <상여금> 테이블의 '부서', '상여내역' 그리고 '상여금'에 대해 부서별 상여내역별 소계와 전체 합계를 검색하시오.(단, 속성명은 '상여금합계'로 하고, ROLLUP함수를 사용할 것)

    • SELECT 부서, 상여내역, SUM(상여금) AS 상여금 합계 FROM 상여금 GROUP BY ROLLUP(부서, 상여내역);
  • <상여금> 테이블의 '부서', '상여내역' , 그리고 '상여금'에 대해 부서별 상여내역별 소계와 전체 합계를 검색하시오(단, 속성명은 ' 상여금합계'로 하고, CUBE 함수를 사용할 것)

    • SELECT 부서, 상여내역, SUM(상여금) AS 상여금 합계 FROM 상여금 GROUP BY CUBE(부서,상여내역)

프로시저(Procedure)

  • 프로시저란 절차형 SQL을 활용하여 특정기능을 수행하는 일종의 트랜잭션언어로, 호출을 통해 실행되어 미리 저장해 놓은 SQL 작업을 수행한다.

프로시저의 구성도

  • 프로시저

  • DECLARE(필수)

  • BEGIN(필수)

    • CONTROL
    • SQL
    • EXCEPTION
    • TRANSACTION
  • END(필수)

  • DECLAERE

    • 프로시저의 명칭, 변수, 인수, 데이터 타입을 정의하는 선언이다
  • BEGIN / END

    • 프로시저의 시작과 종료를 의미한다
  • CONTROL

    • 조건문 또는 반복문이 삽입되어 순차적으로 처리된다
  • SQL

    • DML, DCL이 삽입되어 데이터 관리를 위한 조회, 추가, 수정, 삭제 작업을 수행한다
  • EXCEPTION

    • BEGIN~END 안의 구문 실행 시 예외가 발생하면 이를 처리하는 방법을 정의
  • TRANSACTION

    • 수행된 데이터 작업들을 DB에 적용할지 취소할지를 결정

프로시저 생성

  • 프로시저를 생성하기 위해서는 CREATE PROCEDURE 명령어를 사용한다

표기형식

CREATE [ OR REPLACE] PROCEDURE 프로시저명(파라미터)

[지역변수 선언]

BEGIN

프로시저 BODY;

END;
  • OR REPLACE

    • 선택적인(Optional) 예약어. 이예약어를 사용하면 동일한 프로시저 이름이 존재하는 경우, 기존의 프로시저를 대체할 수 있다.
  • 프로시저명

    • 생성하려는 프로시저의 이름을 지정
  • 파라미터

    • 프로시저 파라미터로는 다음과 같은 것들이 올 수 있다
      • IN
        • 호출 프로그램이 프로시저에게 값을 전달할 때 지정한다
      • OUT
        • 프로시저가 호출 프로그램에게 값을 반환할 때 지정한다
      • INOUT
        • 호출 프로그램이 프로시저에게 값을 전달하고, 프로시저 실행 후 호출 프로그램에 값을 반환할 때 지정한다.
      • 매개변수명
        • 호출 프로그램으로부터 전달 받은 값을 저장할 변수의 이름을 지정한다.
      • 자료형
        • 변수의 자료형을 지정한다
  • 프로시저 BODY

    • 프로시저의 코드를 기록하는 부분
    • BEGIN에서 시작하여 END로 끝나며, BEGIN과 END 사이에는 적어도 하나의 SQL문이 있어야한다
  • EX) '사원번호'를 입력받아 해당 사원의 '지급방식'을 "S"로 변경하는 프로시저를 생성하시오

      1. CREATE OR REPLACE PROCEUDER emp_change_s(i_사원번호 IN INT)
      2. IS
      3. BEGIN
    
          4. UPDATE 급여 SET 지급방식 = 'S' WHERE 사원번호 = i_사원번호;
    
          5. EXCEPTION
    
          6. WHEN PROGRAM_ERROR THEN
    
          7. ROLLBACK;
    
          8. COMMIT;
    
      9. END;
    • 해설

      1. 호출 프로그램이 전달한 값을 'i_사원번호'에 저장한 후 사용하는 프로시저 'emp_change_s'를 생성한다
      2. 변수를 선언하는 예약어로, 변수를 사용하지 않으므로 예약어만 입력한다
      3. 프로시저 BODY의 시작을 알리는 예약어로,
      4. 부터 8 까지가 하나의 블록이된다.
      5. <급여> 테이블에서'사원번호'가 i_사원번호'로 받은 값과 같은 튜플의 '지급방식'을"S"로 갱신한다
      6. 예외처리의 시작을 알리는 예약어이다.
      7. ERROR가 발생할 경우 수행되는 문장으로, ROLLBACK을 수행한다
      8. 4에서 변경한 내역을 데이터베이스에 반영하는 트랜잭션 명령어이다.
      9. 프로시저 BODY의 종료를 알리는 예약어이다.

프로시저 실행

프로시저를 실행하기 위해서는 EXECUTE 명령어 또는 CALL 명령어를 사용하며, EXECUTE 명령어를 줄여서 EXEC로 사용하기도 한다

표기 형식

  • EXECUTE 프로시저명;
  • EXEC 프로시저명;
  • CALL 프로시저명;
    • EX) '사원번호' 32를 인수로하여 위에서 생성된 emp_change_s 프로시저를 실행하시오

      • EXEC emp_cahnge_s(32);

프로시저 제거

  • 프로시저를 제거하기 위해서는 DROP PROCEDURE 명렁어를 사용한다

  • DROP PROCEDURE 프로시저명;

  • ex) 위에서 생성된 프로시저 emp_change_s를 제거하시오

    • DROP PROCEDURE emp_change_s;

트리거(Trigger)

트리거(Trigger)의 개요

  • 트리거는 데이터베이스 시스템에서 데이터의 삽입(insert), 갱신(Update), 삭제(Delete)등의 이벤트(Event)가 발생할 때마다 관련 작업이 자동으로 수행되는 절차형 SQL이다.

    • 트리거는 데이터베이스에 저장되며, 데이터 변경 및 무결성 유지, 로그메시지 출력 등의 목적으로 사용된다
    • 트리거의 구문에는 DCL(데이터 제어어)을 사용할 수 없으며 , DCL이 포함된 프로시저나 함수를 호출하는 경우에도 오류가 발생한다.
    • 트리거에 오류가 있는 경우 트리거가 처리하는 데이터에도 영향을 미치므로 트리거를 생성할 때 세심한 주의가 필요하다

트리거의 구성

  • 트리거는 선언, 이벤트, 시작, 종료로 구성되며, 시작과 종료 구문 사이에는 제어(CONTROL),SQL, 예외(EXCEPTION)가 포함된다

트리거의 구성도

  • 트리거

    DECLARE(필수)

    EVENT (필수)

    BEGIN (필수)

    • CONTROL

    • SQL

    • EXCEPTION

      END (필수)

    • DECLARE

      • 트리거의 명칭, 변수 및 상수, 데이터 타입을 정의하는 선언부이다
    • EVENT

      • 트리거가 실행되는 조건을 명시한다
    • BEGIN / END

      • 트리거의 시작과 종료를 의미한다
    • CONTROL

      • 조건문 또는 반복문이 삽입되어 순차적으로 처리된다.
    • SQL

      • DML문이 삽입되어 데이터 관리를 위한 조회, 추가, 수정, 삭제 작업을 수행한다
    • EXCEPTION

      • BEGIN ~ END 안의 구문 실행 시 예외가 발생하면 이를 처리하는 방법을 정의한다

트리거의 생성

  • 트리거를 생성하기 위해서는 CREATE TRIGGER 명령어를 사용한다.

      CREATE [ OR REPLACE] TRIGGER 트리거명 [동작시기 옵션][동작 옵션] ON 테이블명
    
      REFERENCING [NEW | OLD] AS 테이블명
    
      FOR EACH ROW
    
      [WHEN 조건식]
    
      BEGIN
    
      트리거 BODY;
    
      END;
    • OR REPLACE

      • 선택적인(Optional) 예약어 이다. 이 예약어를 사용하면 동일한 트리거 이름이 존재하는 경우, 기존 트리거를 대체할 수 있다.
    • 동작시기 옵션

      • 트리거가 실행될 때를 지정한다. 옵션에는 AFTER와 BEFORE가 있다.
        • AFTER
          • 테이블이 변경된 후에 트리거가 실행된다
        • BEFORE
          • 테이블이 변경되기 전에 트리거가 실행된다
    • 동작 옵션

      • 트리거가 실행되게 할 작업의 종류를 지정한다. 옵션에는 INSERT, DELETE, UPDATE가 있다
        • INSERT
          • 테이블에 새로운 튜플을 삽입할 때 트리거가 실행된다
        • DELETE
          • 테이블의 튜플을 삭제할 때 트리거가 실행된다
        • UPDATE
          • 테이블의 튜플을 수정할 때 트리거가 실행된다
    • NEW | OLD

      • 트리거가 적용될 테이블의 별칭을 지정한다
        • NEW
          • 추가되거나 수정에 참여할 튜플들의 집합(테이블)을 의미한다
        • OLD
          • 수정되거나 삭제 전 대상이 되는 튜플들의 집합(테이블)을 의미한다
    • FOR EACH ROW

      • 각 튜플마다 트리거를 적용한다는 의미이다.
    • WHEN 조건식

      • 선택적인(Optional) 예약어이다. 트리거를 적용할 튜플의 조건을 지정한다
    • 트리거 BODY

      • 트리거의 본문 코드를 입력하는 부분이다
      • BEGIN으로 시작해서 END으로 끝나며, 적어도 하나 이상의 SQL문이 있어야 한다. 그렇지 않으면 오류가 발생한다.
    • ex) <학생>테이블에 새로운 튜플이 삽입될 때, 삽입되는 튜플에 학년 정보가 누락됐으면 '학년'속성에 "신입생"을 저장하는 트리거를 '학년정보_tri'라는 이름으로 정의하시오

       

    1. DECLARE
      
      1. p_name employee.name%TYPE;
      2. CURSOR cur_name(ff INT)
      
          IS
      
      3. SELECT name FROM employee WHERE id >= ff;
      
          BEGIN 
      
      4. OPEN cur_name(20);
      5. LOOP
      6.       FETCH cur_name INTO p_name;
      7.       EXIT WHEN cur_name%NOTFOUND;
      8.       DBMS_OUTPUT.PUT_LINE(p_name);
      9. END LOOP;
      10. CLOSE cur_name;
      11. END;
      
    • 해설
      1. 새로 추가될 튜플들의 집합 NEW의 별칭을 로 명명한다.
      2. 모든 튜플을 대상으로한다.
      3. 에서 '학년' 속성이 NULL인 튜플에 '학년정보_tri'가 적용된다
      4. 의 '학년' 속성에 "신입생"을 저장한다.
        • 2에서 NEW 또는 OLD로 지정된 테이블 이름 앞에는 콜론(:) 이 들어간다
        • A := B
          • A에 B를 저장하라는 의미로, '='가 아닌 ':='를 사용한다

트리거의 제거

  • DROP TRRIGER 트리거명;

  • ex ) '학년정보_tri'라는 트리거를 제거하는 SQL문을 작성하시오

    • DROP TRIGGER 학년정보_tri;

사용자 정의함수의 개요

  • 사용자 정의 함수는 프로시저와 유사하게 SQL을 사용하여 일련의 작업을 연속적으로 처리하며, 종료 시 처리 결과를 단일값으로 반환하는 절차형SQL이다.

    • 사용자 정의 함수는 데이터베이스에 저장되어 SELECT , INSERT, DELETE, UPDATE 등 DML문의 호출에 의해 실행된다.
    • INSERT, DELETE, UPDATE를 통한 테이블조작은 할 수 없고 SELECT를 통한 조회만 할 수 있다.

사용자 정의 함수 구성 

  • 사용자 정의 함수의 구성은 프로시저와 유사하다. 프로시저의 구성에서 RETURN만 추가하면된다

    사용자 정의 함수의 구성도

     

DECLARE (필수)

 

BEGIN (필수)

  • 사용자 정의 함수
  • CONTROL

  • SQL

  • EXCEPTION

  • RETURN (필수)

END (필수)

 

  • DECLARE

    • 사용자 정의 함수의 명칭, 변수, 인수, 데이터 타입을 정의하는 선언부이다.
  • BEGIN / END

    • 사용자 정의 함수의 시작과 종료를 의미한다
  • CONTROL

    • 조건문 또는 반복문이 삽입되어 순차적으로 처리된다
  • SQL

    • SELECT 문이 삽입되어 데이터 조회 작업을 수행한다
  • EXCEPTION

    • BEGIN ~ END 안의 구문 실행 시 예외가 발생하면 이를 처리하는 방법을 정의한다
  • RETURN

    • 호출 프로그램에 반환할 값이나 변수를 정의한다.

사용자 정의 함수 생성

  • 사용자 정의 함수를 생성하기 위해서는 CREATE FUNCTION명령어를 사용한다

  • 표기 형식

      CREATE [OR REPLACE ] FUNCTION 사용자 정의 함수명[파라미터]
      [지역변수 선언]
    
      BEGIN
    
      사용자 정의 함수 BODY;
    
      RETURN 반환값;
    
      END;
  • OR REPLACE

    • 선택적인(Optional) 예약어이다. 이 예약어를 사용하면 동일한 사용자 정의 함수의 이름이 이미 존재하는 경우, 기존의 사용자 정의 함수를 대체할 수 있다.
  • 파라미터

    • 사용자 정의 함수의 파라미터로는 다음과 같은 것들이 올 수 있다.
      • IN
        • 호출 프로그램이 사용자 정의 함수에게 값을 전달할 때 지정된다
      • 매개변수명
        • 호출 프로그램으로부터 전달받은 값을 저장할 변수의 이름을 지정한다
      • 자료형
        • 변수의 자료형을 지정한다.
  • 사용자 정의 함수 BODY

    • 사용자 정의 함수의 코드를 기록하는 부분이다.
    • BEGIN에서 시작하여 END로 끝나며, BEGIN과 END 사이에는 적어도 하나의 SQL문이 있어야 한다.
  • RETURN 반환값

    • 반환할 값이나 반환할 값이 저장된 변수를 호출 프로그램으로 돌려준다.
  • ex) 'i_성별코드'를 입력받아 1이면 "남자"를, 2면"여자"를 반환하는 사용자 정의 함수를 'Get_S_성별'이라는 이름으로 정의하시오

      1. CREATE FUNCTION Get_S_성별(i_성별코드 IN INT)
      2. RETURN VARCHAR2
      3. IS
    
          BEGIN
    
          4. IF i_성별코드 = 1 THEN
    
            RETURN '남자';
    
          5. ELSE
    
            RETURN '여자';
    
                6. END; IF;
    
          END;
  • 해설

    1. 호출 프로그램이 전달한 값을 'i_성별코드'에 저장한 후 사용하는 사용자 정의함수 'Get_S_성별'을 생성한다
    2. 블록에서 리턴할 데이터의 자료형을 정의한다. 자료형의 크기는 입력하지 않는다.
      • 형식 : RETURN [자료형]
    3. 변수 선언을 위해 사용하는 예약어로, 변수를 사용하지 않으므로 예약어만 입력한다.
    4. 'i_성별코드'가 아니면 "남자"를 반환하고
    5. 'i_성별코드'가 1이 아니면"여자를 반환한다.
    6. IF문의 끝

사용자 정의 함수 실행

  • 사용자 정의 함수는 DML에서 속성명이나 값이 놓일 자리를 대체하여 사용된다

  • 표기 형식

    SELECT 사용자 정의 함수명 FROM 테이블명;

    INSERT INTO 테이블명(속성명) VALUES (사용자 정의 함수명);

    DELETE FROM 테이블명 WHERE 속성명 = 사용자 정의 함수명;

    UPDATE 테이블명 SET 속성명 = 사용자 정의 함수명;

  • ex) 다음의 <사원> 테이블을 출력하되, '성별코드'는 앞에서 사용자 정의 함수 'Get_S_성별'에 값을 전달하여 반환받은 값으로 대체하여 출력하시오

    • SELECT 이름, Get_S_성별(성별코드) FROM 사원;

사용자 정의 함수 제거

  • 사용자 정의 함수를 제거하기 위해서는 DROP FUNCTION 명령어를 사용한다
    • DROP FUNCTION 사용자 정의 함수명;
    • EX ) 앞에서 생성된 사용자 정의 함수 'Get_S_성별'을 제거하시오
      • DROP FUNCTION Get_S_성별;

제어문의 개요

  • 절차형 SQL은'절차형' 이라는 말 그대로 SQL 명령어가 서술된 순서에 따라 위에서 아래로 차례대로 실행되는데, 제어문은 이러한 진행 순서를 변경하기 위해 사용하는 명령문이다.
    • 제어문의 종류에는 IF, LOOP, GOTO 등이 있다

IF문

  • 조건에 따라 실행할 문장을 달리하는 제어문이다.

    • 형식1 : 조건이 참일 때만 실행한다

        IF 조건 THEN
      
        실행할 문장1;
      
        ELSIF 조건 THEN
      
        실행할 문장2;
      
        ELSE 
      
        실행할 문장3;
      
        END IF;

      ex) x가 10보다 크면 화면에 "true"를 출력하기

      ```sql

    1. DECLARE
    2. x INT := 20;
    3. BEGIN
    4. IF x > 10 THEN
    5. DBMS_OUTPUT.PUT_LINE('true');
    6. END IF;
    7. END;
    • 해설
    1. 프로시저, 트리거, 사용자 정의 함수를 사용하지 않고 절차형 SQL을 실행하고 싶을 때 사용하는 예약어이다. 첫 문단에 그대로 적는다.
    2. 정수형 변수 x를 선언하고 20으로 초기화 한다.
    3. 절차형 SQL의 시작이다.
    4. x가 10보다 크면 5번 문장을 실행하고, 아니면 6번으로 이동하여 IF문을 종료한다. x가 10보다 크므로 5번으로 이동한다.
    5. 4번의 조건식이 참일 경우 실행할 문장이다. 화면에 true가 출력된다
    6. IF문의 끝이다
    7. 절차형 SQL의 끝이다.

커서의 개념

  • 커서는 쿼리문의 처리 결과가 저장되어 있는 메모리 공간을 가리키는 포인터(Pointer)이다
    • 커서는 내부에서 자동으로 생성되어 사용되는 묵시적 커서와, 사용자가 직접 정의해서 사용하는 명시적 커서가 있다.
    • 커서의 수행은 열기(Open), 패치(Fetch), 닫기(Close)의 세 단계로 진행된다.
    • 묵시적 커서는 수행된 쿼리문의 정상적인 수행 여부를 확인하기 위해 사용되며, 명시적 커서는 수행된 쿼리문의 정상적인 수행 여부를 확인하기 위해 사용되며, 명시적 커서는 쿼리문의 결과를 저장하여 사용함으로써 동일한 쿼리가 반복 수행되어 데이터베이스 자원이 낭비되는 것을 방지한다.

묵시적 커서(implicit Cursor)

  • 묵시적 커서는 DBMS 자체적으로 열리고(Open) 패치(Fetch) 되어 사용이 끝나면 닫히지만(Close) 커서의 속성을 조회하여 사용된 쿼리 정보를 열람하는 것이 가능하다

  • 커서의 속성

    • SQL%FOUND
      • 쿼리 수행의 결과로 패치(Fetch)된 튜플 수가 1개 이상이면 TRUE
    • SQL%NOTFOUND
      • 쿼리 수행의 결과로 패치(Fetch)된 튜플 수가 0개이면 TURE
    • SQL%ROWCOUNT
      • 쿼리 수행의 결과로 패치(Fetch)된 튜플 수를 반환
    • SQL%ISOPEN
      • 커서가 열린(Open)상태이면 TRUE
      • 묵시적 커서는 자동으로 생성된 후 자동으로 닫히기 때문에 항상 FALSE
  • ex) 다음은 테이블에서 UPDATE 를 수행하고 갱신된 튜플의 수를 확인하는 절차형 SQL을 PL/SQL로 구현한 것이다.

    •   BEGIN
        UPDATE SCORE SET COND = 25 WHERE DEPT = 'PR';
      
        DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
      
        END;
    1. 테이블에서 'DEPT' 속성이 "PR"인 튜플의 'COND' 속성의 값을 25로 수정한다
    2. 1의 결과로 변경되는 튜플은 2,3,5행 세개이므로 3이출력된다.

명시적 커서(Explicit Cursor)

  • 명시적 커서는 사용자가 직접 정의해서 사용하는 커서로 , 주로 절차형 SQL에서 SELECT문의 결과로 반환되는 여러 튜플들을 제어하기 위해 사용된다

    • 커서는 기본적으로 '열기(Open) - 패치(Fetch) - 닫기(Close)' 순으로 이루어지며, 명시적 커서로 사용하기 위해서는 열기 전엔 선언(Declare)을 해야 한다.

    • 선언(Declare) 형식

      CURSOR 커서명(매개변수1, 매개변수2, - - - )

      IS

      SELECT문;

      • CURSOR, IS는 예약어로 그대로 적으며, 커서명은 사용자가 임의로 정한다
      • (매개변수1, 매개변수2 , - - -)는 SELECT 문의 WHERE 절에 사용할 수 있으며 생략이 가능하다.
      • 커서가 열릴(Open) 때 수행할 SELECT문을 작성한다. 커서는 SELECT 문의 실행 결과가 저장된 곳의 시작 위치를 가리킨다.
    • 열기(Open) 형식

      • OPEN 커서명(매개변수1, 매개변수2, - - - );
      • 커서를 사용하기 전에 반드시 적는다. OPEN은 예약어로 그대로 적고, 선언 시 입력한 커서명과 메개변수를 적는다.
    • 패치(Fetch) 형식

      • FETCH 커서명 INTO 변수1, 변수2 , - - - ;
      • FETCH , INTO는 예약어로 그대로 적는다.
      • 커서명과 커서에 저장된 튜플들의 각 속성과 같은 자료형을 가진 변수를 적고 데이터를 가져온다
    • 닫기(Close) 형식

      • CLOSE 커서명;
      • 사용된 커서는 메모리 해제를 위해반드시 닫아야한다.
      • CLOSE는 예약어로 그대로 적고, 사용한 커서명을 뒤에서 적는다
    • EX) 다음은 테이블로부터 id가 20보다 크거나 같은 튜플의 name을 출력하는 절차형 SQL을 PL/SQL로 구현한 것이다

        DECLARE
      
        1. p_name employee.name%TYPE;
        2. CURSOR cur_name(ff INT)
      
            IS
      
        3. SELECT name FROM employee WHERE id >= ff;
      
            BEGIN 
      
        4. OPEN cur_name(20);
        5. LOOP
        6.       FETCH cur_name INTO p_name;
        7.       EXIT WHEN cur_name%NOTFOUND;
        8.       DBMS_OUTPUT.PUT_LINE(p_name);
        9. END LOOP;
        10. CLOSE cur_name;
        11. END;
      • 해설
      1. 테이블의 'name' 속성의 자료형과 동일한 변수 p_name을 선언한다.
      2. 전달받은 값을 ff에 저장한 후 사용하는 커서 cur_name을 선언한다
      3. 2에서 선언된 커서가 OPEN될 때 수행할 SELECT 문을 정의한다. 테이블의 'id' 속성이 ff보다 크거나 같은 튜플의 'name' 속성을 조회한다.
      4. 커서 cur_name을 연다 . 20은 2번의 ff로 전달되어 "SELECT name FROM employee WHERE id ≥ 20;"이 수행되고, cur_name에는 결과가 저장된 메모리의 시작 위치가 저장된다.
      5. LOOP문의 시작이다. 6~8번 문장을 반복하여 수행한다
      6. 커서 cur_name으로부터 데이터를 가져와 p_name에 저장한다
      7. cur_name의 %NOTFOUND 속성이 TRUE를 반환, 즉 더 불러올 값이 없으면 LOOP문을 빠져나간다.
      8. p_name의 값을 화면에 출력한다
      9. 커서 cur_name을 닫는다.