본문 바로가기
DATABASE/ORACLE

[PL/SQL] 예제 (1) - 1~100의 수를 더하는 과정을 출력

by 허도치 2020. 1. 22.

  [ WITH순환절, CURSOR, 동적쿼리 ] 이용하여 1~100을 더하는 과정을 출력하는 예제를 만들어 보았다.

 

 

1. 예제 소스.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/** DBMS를 출력 **/
SET SERVEROUTPUT ON
 
/** 경과 시간을 출력 **/
SET TIMING ON
 
/**
 * 1~100을 더하는 과정을 출력하시오.
 */
DECLARE
    /** 계산용 변수 **/
    V_START_NUM     NUMBER;
    V_END_NUM       NUMBER;
    V_ROWNUM        NUMBER;
    V_NUM           NUMBER;
    V_TOTAL         NUMBER;
    
    /** 결과처리용 변수 **/
    V_RESULT        VARCHAR2(4000);
    
    /** 예외처리용 변수 **/
    V_ERR_MSG       VARCHAR2(4000);
    E_END_POINT     EXCEPTION;
    E_IGNORE        EXCEPTION;
    
    /** 동적쿼리용 변수 **/
    V_QRY           VARCHAR2(4000);
    
    /** 커서 **/
    TYPE MY_CURSOR IS REF CURSOR;
    CUR1            MY_CURSOR;
 
BEGIN
    /** 변수 초기화 **/
    V_START_NUM := 1;
    V_END_NUM := 100;
    
    V_NUM := 0;
    V_TOTAL := 0;
    
    V_RESULT  := '';
    V_ERR_MSG := '';
    
    V_QRY := '';
    
    BEGIN
        /** WITH 순환절 && 동적쿼리 && CURSOR **/
        V_QRY := '
            WITH NUMBERS ( NUM ) AS (
                SELECT :1 AS NUM
                  FROM DUAL
                 UNION ALL 
                SELECT A.NUM + 1 AS NUM
                  FROM NUMBERS A
                 WHERE A.NUM < :2
            )
            SELECT ROWNUM
                 , T1.NUM
              FROM NUMBERS T1
        ';
        
        /** 동적쿼리에 변수를 대입하고 CURSOR로 실행 **/
        OPEN CUR1 FOR V_QRY USING V_START_NUM, V_END_NUM;
        LOOP
            /** CURSOR에서 조회된 COLUMN을 차례대로 변수에 저장 **/
            FETCH CUR1 INTO V_ROWNUM, V_NUM;
            
            /** 조회된 ROW가 없으면 LOOP를 탈출 **/
            EXIT WHEN CUR1%NOTFOUND;
            
            /** 1~100까지 더하는 과정 출력 **/
            DBMS_OUTPUT.PUT_LINE( V_ROWNUM||' | '|| V_TOTAL||' + '||V_NUM||' = '||( V_TOTAL+V_NUM ) );
            
            /** 집계 **/
            V_TOTAL := V_TOTAL + V_NUM;
            
        END LOOP;
        CLOSE CUR1;
        
        /** 집계가 100회 수행되었는지 확인 **/
        --V_ROWNUM := 141;
        IF V_ROWNUM != 100 THEN
            /** 사용자정의 예외 발생 **/
            RAISE E_END_POINT;
        END IF;
        
        /** 집계결과가 정상적인지 확인 **/
        --V_TOTAL := 9999;
        IF V_TOTAL != 5050 THEN
            /** 사용자정의 예외 발생 **/
            RAISE E_IGNORE;
        END IF;
        
        /** 결과 메시지 생성 **/
        V_RESULT := '1~100을 모두 더한 값은 '||CHR(39)||V_TOTAL||CHR(39)||'입니다.';
    
    /** 
     * 예외처리2
     * 처리되지않은 오류는 상위블록의 EXCEPTION으로 전파됨.
     **/
    EXCEPTION
        /** E_END_POINT EXCEPTION을 CATCH **/
        WHEN E_END_POINT THEN
            /** SQLCODE와 SQLERRM을 정의한 예외를 발생(상위 EXCEPTION으로 전파) **/
            RAISE_APPLICATION_ERROR( -20001'100회가 수행되지 않았습니다. [수행:'||V_ROWNUM||']' );
        
        /** E_IGNORE EXCEPTION을 CATCH **/
        WHEN E_IGNORE THEN
            /** 결과값에 오류를 저장하고 정상진행 **/
            V_RESULT := '결과값이 틀렸습니다. [예상:5050][실제:'||V_TOTAL||']';
        
    END
    ;
    
    /** 결과 출력 **/
    DBMS_OUTPUT.PUT_LINE( '=================[정상종료]=================' );
    DBMS_OUTPUT.PUT_LINE( V_RESULT );
    
/** 예외처리1 **/
EXCEPTION
    /** 모든 EXCEPTION을 CATCH **/
    WHEN OTHERS THEN
        /** 오류메시지 생성 **/
        V_ERR_MSG := 'SQLCODE='||SQLCODE||', MESSAGE='||SQLERRM;
        
        /** 오류 출력 **/
        DBMS_OUTPUT.PUT_LINE( '=================[오류]=================' );
        DBMS_OUTPUT.PUT_LINE( V_ERR_MSG );
 
END
;
cs

 

 

2. 실행 결과.

   2-1. 정상.

         - 예상했던 값이 출력되면서 정상 종료.

 

   2-2. 'E_END_POINT' EXCEPTION 발생.

         - 수행횟수가 예상했던 횟수가 아니면 오류를 발생하도록 하였으므로 오류로 종료.

 

   2-3. 'E_IGNORE' EXCEPTION 발생.

         - 결과값이 틀렸을 경우, 다음 단계를 정상적으로 수행하도록 하였으므로 정상 종료.

 

 

3. 마치며.

   - 이렇게까지 사용할 일은 거의 없을테지만, PL/SQL을 이렇게도 사용할 수 있다는 것을 보여주기위해 만들어보았다.

   - 예제에 나온 것들만 알아도 PL/SQL이나 PROCEDURE를 사용하는데 무리가 없을 것이라고 생각된다.

댓글