프로그래밍/자바(java) 융합개발자 2차

[취성패] 자바 배우기 - 9일차 일지(PL/SQL 제어문, 커서)

aSpring 2020. 12. 24. 08:55
728x90
728x90

 

내일이 크리스마스라서

오늘이 이번주의 마지막 수업!

와 벌써 2주가 지났다니!

근데 아는건.. 아직.. 없는 것 같다.


우리가 하는 일 -> Application을 만드는 일

                        - 1) GUI <-> CLI     화면

                        - 2) Data -> file, DB(우리가 하고있는 것 - isert, select), 메모리 등에 저장되어 있음

                        - 3) Control(제어) -> 알고리즘(자료구조)이라고 함 => 제어문(장)

 

제어문

1. 반복문  1) For 반복문 : For ~ End; 안에 있는 영역이 반복해서 실행됨

              2) While 반복문

 

2. 분기문(branch, 조건문)   1) If  조건문

                                    2) Switch ~ Case


 

12. PL/SQL 제어문 사용법 익히기

- 조건문과 반복문으로 나눌 수 있음

- 조건문 :  IF문, CASE문

- 반복문 : Basic Loop문, While문 - 반복 횟수를 알 수 없을 경우

              For문 - 반복 횟수를 지정할 경우

 

1. 조건문(IF문) :

   유형 1. IF ~ END IF 문장

IF (조건) THEN
  실행문장;   -- if 뒤의 조건이 True가 되면 실행문장을 실행, False가 되면 실행문장을 실행하지않고 End
END IF;

ex) if price > 20000 then

 

유형 1번의 :

EMPLOYEES 테이블에서 employee_id 203 번인 사원의 employee_id , first_name, department_id , dname 을 출력하세요. ( DNAME 의 값은 아래와 같습니다.)

department_id 10 이면 ’Administration’ ,

department_id 20 이면 ‘Marketing’ ,

department_id 30 이면 ‘Purchasing’ ,

department_id 40 이면 'Human Resources’ 로 출력하세요

 

 

부서 id가 10이면 administration를 집어넣고

부서 id가 20이면 marketing

부서 id가 30이면 purchasing

부서 id가 40이면 human resources를 집어넣는다.

 

결과 값이 나오지 않으면

set serveroutput on;

입력해서 설정 해주어야 함

 

IF (조건식) THEN

    ~~~                      -> 조건에 맞으면 ~~ 실행

elsif (조건식1) then

    ~~~1                    -> 조건식1에 맞으면 ~~1 실행

esle                          

    ~~~2                    -> 아니면 ~~~2 실행

END IF

 

 

 

유형 2. IF ~ THEN ~ ELSIF ~ END IF 문장(조건이 여러 개일 경우 사용)

IF ( 조 건 1 ) THEN
   실행 문장 ;
ELSIF ( 조 건 2 ) THEN
   실행 문장 ;
ELSIF ( 조 건 3 ) THEN
   실행 문장 ;
END IF ;

: EMPLOYEES 테이블에서 employee_id 203 번인 사원의 employee_id , first_name , department_id , dname 을 출력하세요. DNAME 의 값은 아래와 같습니다.

 

department_id 10 이면 ’Administration’ ,

department_id 20 이면 ‘Marketing’ ,

department_id 30 이면 ‘Purchasing’ ,

department_id 40 이면 'Human Resources’ 로 출력하세요

 

 

-- 혼자 해보기

declare
    empid employees.employee_id%TYPE;
    fname employees.first_name%TYPE;
    dptid employees.department_id%TYPE;
    dname varchar2(20);
begin
    select employee_id, first_name, department_id
    into empid, fname, dptid
    from employees
    where employee_id = 203;
    
    if (dptid = 10) then
        dname := 'administration';
    END IF;
    if (dptid = 20) then
        dname := 'Marketing';
    END IF;   
    if (dptid = 30) then
        dname := 'Purchasing';
    END IF;   
    if (dptid = 40) then
        dname := 'Human Resources';
    END IF;
    DBMS_OUTPUT.PUT_LINE (empid||'번 사원 '||fname||'씨는 '||dptid||'-'||dname||'부서 입니다.');
end;

-- 또는
declare
    empid employees.employee_id%TYPE;
    fname employees.first_name%TYPE;
    dptid employees.department_id%TYPE;
    dname varchar2(20);
begin
    select employee_id, first_name, department_id
    into empid, fname, dptid
    from employees
    where employee_id = 203;
    
    if (dptid = 10) then
        dname := 'administration';
    ElsIF (dptid = 20) then
        dname := 'Marketing';
    elsif (dptid = 30) then
        dname := 'Purchasing';
    elsif (dptid = 40) then
        dname := 'Human Resources';
    END IF;
    DBMS_OUTPUT.PUT_LINE (empid||'번 사원 '||fname||'씨는 '||dptid||'-'||dname||'부서 입니다.');
end;

 

유형 3. IF~THEN~ELSE~END IF ( 조건이 2개 일 경우 사용)

IF  ( 조 건 1 ) THEN
  실행 문장1 ;   -> 조건 1이 맞으면 실행문장1 실행
ELSE
  실행 문장2 ;    -> 조건 1이 아니라면 실행문장2 실행
END IF ;

: 사용자에게 employee_id 를 입력 받은 후 EMPLOYEES 테이블에서 employee_id 가 입력

받은 번호인 사원의 employee_id , first_name , salary , salary*commission_pct 값을 출력

하되 해당 사원의 commission_pct 값이 이 0보다 크면 salary*commission_pct 의 금액을

출력하고, 0 보다 작으면 ‘ xx사원의 보너스는 없습니다라는 문장을 출력하세요.

 

보너스 없는 사원들.. 불쌍..

 

set verify off -> 유효성 검사를 끄는 것

자세한 내용은 네이버 블로그를 참조했다.

 

더보기

SET VERIFY ON/OFF;

SQL 명령어나 PL/SQL에서 &를 이용한 치환 변수 등을 사용할 때 치환되기 전 후의 자세한 값을

보일 건지의 여부를 결정하며 기본값은 ON

 

1. set verify off인 경우

SET VERIFY OFF
SELECT &LIST
FROM &TAB
WHERE ROWNUM < 3;

LIST의 값을 입력하십시오 : ename

TAB의 값을 입력하십시오 : emp

 

ENAME
---------
SMITH
ALLEN

 

2. set verify off인 경우

set verify on;
select &list
from &tab
where rownum < 3;

LIST의 값을 입력하십시오 : ename

구 1: select &list
신 1: select ename

TAB의 값을 입력하십시오 : emp

구 2: from &tab
신 2: from emp
ENAME
---------
SMITH
ALLEN

출처 : blog.naver.com/kmn_5/100090620483

 

SET VERIFY ON/OFF

SET VERIFY ON/OFF : SQL명령어나 PL/SQL에서 &를 이용한 치환 변수등을 사용할...

blog.naver.com

개발자를 위하여(오라클자바커뮤니티) - Daum 카페

 

개발자를 위하여(오라클자바커뮤니티)

IT실무전문교육센터(구로디지털단지역 2분거리) http://topcredu.co.kr 02)851-4790 3D프린팅, 아두이노알고리즘, 스마트로봇교육, 오라클, 자바, 닷넷, 스마트폰 프로그래머 실무교육

cafe.daum.net

 

 

 

2. CASE 조건문

: IF문 보다 깔끔하게 나온다 But CASE문으로 쓸 수 없는 경우도 있다.

CASE  [ 조건 ]                  -- 입력조건
   WHEN 조건 1  THEN  결과 1    -- 입력조건이 1과 맞으면 결과 1 실행
   WHEN 조건 2  THEN  결과 2    -- 입력조건이 2와 맞으면 결과 1 실행
    …
   WHEN 조건 n  THEN  결과 n    -- 입력조건이 n과 맞으면 결과 n 실행
[ ELSE  기본값 ]                -- 입력조건이 어느것과도 맞지 않으면 기본값
END ;

- CASE 문 사용 예 1:

: EMPLOYEES 테이블에서 employee_id 203 번인 사원의 employee_id , first_name ,

department_id , dname 을 출력하세요. DNAME 의 값은 아래와 같습니다.

department_id 10 이면 ’Administration’ ,

department_id 20 이면 ‘Marketing’ ,

department_id 30 이면 ‘Purchasing’ ,

department_id 40 이면 'Human Resources’ 로 출력하세요

v_dqptid가 10이면 v_name에 Administration을 집어넣고, 20이면 marketing ... 

문제에서 시키는대로 203을 넣어주자

 

3. 반복문 - For / While(Do ~ While)

 - 초기값(반복)

 - 증가값

 - 종료조건

 

반복문은 반복 횟수를 알 수 없는 경우에 사용하는 BASIC LOOP 문과 WHILE 문이 있고 반복횟수를 지정하는 FOR 문이 있습니다

 

1) WHILE 반복문

While  조건  LOOP
   PL/SQL 문장 
   PL/SQL 문장 
END LOOP ;

조건을 먼저 확인 후 문장을 수행함

 

BASIC LOOP 문은 나중에 조건을 검색하지만 WHILE 문은 시작부터 조건을 먼저 검사한 후 PL/SQL 문장을 수행하게 됨.  BASIC LOOP 문은 조건이 틀려도 PL/SQL 문장이 1회는 실행이 되지만 WHILE 문은 아예 실행이 되지 않습니다.

 

WHILE 반복문 사용 예 1:

WHILE 반복문을 사용하여 아래의 출력 예시와 같이 출력하세요.

no1       - 초기값 -> 계속 바뀔 것

no1 + 1 - 증가값

no1 < 6 - 종료조건

 

요걸 써주면 되는데 no1이라는 변수를 선언해줘야 함

Declare
    변수 선언
BEGIN    

END;    

 

->

 

2) BASIC LOOP 반복문(Do While문의 한 형태)

LOOP
   PL/SQL 문장 ;
   PL/SQL 문장 ;      -- 두 문장을 n번 반복하는데
   EXIT [ 조건 ] ;    -- 조건에 맞으면 반복 END
END LOOP ; 

DO 문장을 먼저 한 번은 수행 후 -> 조건을 확인함

 

BASIC LOOP 문 사용 예 1 :

Loop 문을 사용하여 화면에 0 부터 5 까지의 숫자를 아래와 같이 출력하세요.

no1이 5보다 크면 loop 종료 -> 6부터 종료

 

앞의 WHILE문과 LOOP문의 차이 ex) no1에 6을 집어넣으면

- LOOP : 최소 한 번은 실행 시키고 종료 조건에 맞으면 반복 종료

6

- WHILE : 조건에 맞는 동안만 실행 -> 조건에 맞지 않으면 한 번도 실행되지 않고 종료될 수 있음

 

조건에 맞지 않아 실행 자체를 시키지 않음

 

 

3) FOR 반복문반복 횟수를 지정 가능함

FOR counter IN [REVERSE] start . . end LOOP
  Statement1 ;
  Statement2 ;
…
END LOOP ;

위 문법에서 counter 는 반복을 카운트 할 변수입니다. 원래 PL/SQL 에서는 사용할 변수를 사용하기 전에 미리 DECLARE 부분에서 선언해야 하지만 FOR 반복문 내에서 사용할 변수는 미리 선언을 하지 않아도 사용 가능합니다.

그리고 IN 다음에 start 부분에 시작번호를 쓰고 .. (점 두 개) 뒤에 end 부분에 끝 숫자를 적으시면 됩니다.

만약 역순으로 반복하려면 IN 다음에 REVERSE 를 쓰고 반복할 횟수를 쓰면 되는데 주의 사항은 REVERSE 를 쓰고 시작번호와 끝 번호는 작은 숫자부터 써야 한다는 것입니다.

 

- FOR 반복문 예 1:

0 – 5 까지 숫자를 화면에 출력하세요.

 

변수 선언을 미리 하지 않아도 되니까 declare는 빼고

begin ~ end;만 써주면 됨

변수 i가 0~5인 동안 i에 입력되는 값을 출력 -> 증가치는 1씩 기본적으로 setting 되어있음


 

13. PL/SQL Cursor(커서) 배우기

 

1. SQL 커서란?

 

원래는 이게 커서

DB 관련해서 커서란? 

- 현재 위치

ex) select * from 테이블 -> 튜플을 한 줄씩 꺼냄(그 때의 위치!) -> 모든 튜플이 나옴 -> 변수에 넣기 위해서

 

오라클 서버에서는 SQL 문을 실행할 때마다 처리(Parse, Execution)를 위한 메모리공간 (이 공간을 이후부터 SQL 커서라고 부르겠습니다)을 사용합니다. 즉 사용자가 요청하는 데이터를 데이터베이스 버퍼 캐쉬에서 커서로 복사 해 온 후 커서에서 원하는 데이터를 추출하여(Fetch) 후속 작업을 하게 된다는 뜻입니다. 이 메모리 공간을 Private SQL Area 라고도 부르며, 오라클의 서버 프로세스 구성이 Dedicated Server 환경이냐 또는 MTS(Multi-Threaded Server)환경이냐에 따라 서버 내에 위치되는 곳이 다릅니다.

SQL 커서는 크게 묵시적 커서(Implicit Cursor)명시적 커서(Explicit Cursor)로 나눌 수 있습니다

 

2. 묵시적 커서(Implicit Cursor) : 함축적, 시적, 내재된 -> 자동이라고 생각하면 됨

 

- 묵시적 커서는 오라클에서 자동적으로 선언해주는 SQL 커서로서, 사용자생성 유무를 알 수 없습니.

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

 

  • 묵시적 커서 속성(Cursor Attribute)
    • SQL%ROWCOUNT : 여기서 SQL은 커서 이름
    • SQL%FOUND       : 데이터가 있다 
    • SQL%NOTFOUND : 데이터가 없다
    • SQL%ISOPEN       : 오픈되어 있다

 

3. 명시적 커서(Explicit Cursor) -> 수동 : 직접 지정해주어야 함

명시적 커서는 사용자가 선언하여 생성 후 사용하는 SQL 커서로, 주로 여러 개의 행을 처리하고자 할 경우 사용합니다.

 

  • 명시적 커서 속성(Cursor Attribute)
    • 커서이름%ROWCOUNT
    • 커서이름%FOUND
    • 커서이름%NOTFOUND
    • 커서이름%ISOPEN

4. 명시적 커서(Explicit Cursor) 처리 단계

커서 만드는 방법

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

CURSOR 커서명
IS
커서에 담고 싶은 내용을 가져오는 서브쿼리

 

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

커서 선언 시 기술했던 서브쿼리를 수행해서 데이터를 커서로 가져 오는 과정

OPEN 커서 이름 ;

3) 명시적 커서로부터 데이터 읽어서 변수로 할당하기(Fetch)

  -> 인출, 꺼내다 : 커서가 현재 그 위치의 데이터를 들고있음(한 줄 단위로)

FETCH 커서_이름 INTO  변수들 ;

4) 명시적 커서 닫기(Close) : 커서를 닫지 않아도 정상적으로 실행은 되지만 창을 열고 닫지 않은 것과 같이 데이터 차지를 하게 됨! 뭔가를 열었으면 닫아서 정리를 해주어야 함 -> 안그럼 성능↓

CLOSE 커서_이름;

 

loop를 언제 종료 할 것인가? c1 안에 값이 없을 때

c1은 department_id=30인 사람들의 데이터를 가지고 있는데 해당하는 데이터가 5개라고 할 때

첫번째 데이터부터 커서가 위치하며 데이터를 vempid, vfname에 employee_id, first_name에 저장한다.

2, 3, 4, 5 .. 로 내려가면서 저장하다가 6으로 가면 더이상 데이터가 없기 때문에 loop 종료.

ex) fetch를 쓰면 1, 2, 3, .. 순서대로 꺼내서 저장 -> 원래 테이블에서 없어짐

 

- 커서 : 자료를 담고있는 임시 변수, 계속 사용 가능, 여러 개를 담을 수 있다. 한 줄씩 꺼내서 처리 하니까

- cursor c1의 내용 : employees 테이블에서 department_id가 30인 employee_id와 first_name을 검색

- loop 에서 c1에서 검색한 employee_id와 first_name을 vempid, vfanem에 저장 -> 출력

  -> 부서 번호가 30인 사람의 사원번호==이름이 출력됨

 

employees 테이블

 

5. Cursor FOR Loop 문 활용하기

FOR  record_name  IN  cursor_name  LOOP
  -- 명시적 커서의 OPEN, FETCH 가 자동적으로 수행됨.
   statement1 ;
   statement2 ;
....
END LOOP ; -- 루프문을 빠져 나갈 때 자동적으로 커서가 CLOSE 됨.

- CURSOR FOR LOOP 1 :

 

employees 테이블의 데이터

 

 

- CURSOR FOR LOOP 2:

이번 예는 Sub query 를 사용하여 작업을 하는 예 입니다.

이 방법은 DECLARE 부분에 커서를 선언 할 필요가 없습니다.

대신 커서에 들어가는 서브쿼리 부분을 IN 뒷부분에 바로 사용하는 방법입니다

 

 

6. 파라미터 Explicit(명시) Cursor

- parametor : 매개변수

  (매개) 인수

  (매개) 인자

--------------

argument

함수 입력값

 

sum(price), count(*)

       ㄴ> parametor, 입력값

함수 사용

 

DECLARE                                              -- 1. 커서를 만든다
CURSOR emp_cur (p_dno employees.department_id%TYPE)) -- 원래는 emp_cur인데 ( )속에 내용이 들어감
IS                                                   --                    ㄴ> (p_dno number)
  SELECT employee_id, first_name, salary
  FROM employees
  WHERE department_id = p_dno;
   ....
  BEGIN                                              --> 2. 만든 커서를 emp_cur를 여기서 사용함
   ....
   OPEN emp_cur(20) ;                                --> 20이 p_dno에 들어감
   ....
   CLOSE emp_cur ;
   OPEN emp_cur(30) ;                                --> 30이 p_dno에 들어감
   ....
   CLOSE emp_cur ;
   ....
END;

7. Explicit Cursor(명시해서 만든 커서)FOR UPDATE 문장

SELECT ...
FROM ...
FOR UPDATE [OF column_reference][NOWAIT | WAIT n];

FOR UPDATE ~ NO WAIT/WAIT; 함께 써줘야 함

 

- FOR UPDATE 구문 사용 예:

DECLARE
CURSOR emp_cur IS
SELECT EMPNO, ENAME, SAL
FROM EMP
WHERE DEPTNO = 20
FOR UPDATE -- 커서 선언시에 FOR UPDATE로 행을 잠금 --> 데이터 변경 시에 lock을 걸면 나 외에 다른 사람들은 데이터를 볼 수는 있지만 isert를 하거나 수정을 못함
NO WAIT ;  -- 내가 FOR UPDATE를 위해 lock을 시도 -> 어? 이미 누가 쓰고 있네? 하면서 바로 튕겨버림
           -- WAIT로 하면 lock이 끝날때까지 기다렸다가 lock이 풀리면 update를 함

BEGIN      
....
OPEN emp_cur ;
....
UPDATE emp
SET sal = sal * 2
WHERE CURRENT OF emp_cur -- 커서 선언 시에 잠긴 행을 무시하고 current(현재걸로) 갱신함(wait걸어놔도 튕기지X고 갱신해버림)
....
CLOSE emp_cur ;
....
END;

 

 

14. ORACLE EXCEPTION(예외처리) : 실행 오류 -> 문장오류X(문장 자체는 오류가 없음)

 

1. PL/SQL 예외란?

- PL/SQL 블록이 PARSE 되는 동안에 오타 등으로 인하여 발생되는 에러를 컴파일 에러(Compilation Error)라고 부르며, PL/SQL 블록이 실행되는 동안에 발생되는 에러를 런타임 에러 (Run-Time Error)라고 부르는데, 이 런타임 에러를 오라클에서는 예외(Exception)라고 칭함.

 

- 오라클의 예외 종류는 두 가지 이며 오라클에서 제공하는 오라클 예외(ORACLE Exception)와 다른 하나는 사용자에 의해 정의되는 사용자 정의 예외(User-defined Exception)있음.

 

- 오라클 예외 : Predefined ORACLE Exception

                    Non-predefined ORACLE Exception’

더보기

- Predefined ORACLE Exception (미리 정의되어 있는 오라클 예외들)

 

- 예외명: ACCESS_INTO_NULL

예외번호: ORA-06530

설명: 정의되지 않은 오브젝트 속성에 값을 할당하고자 했을 때 발생되는 예외.

 

- 예외명: CASE_NOT_FOUND

예외번호: ORA-06592

설명: CASE 문의 WHEN 절에 해당되는 조건이 없고 ELSE 절도 없을 경우에 발생되는 예외.

 

- 예외명: COLLECTION_IS_NULL

예외번호: ORA-06531

설명: 선언되지 않은 컬렉션 (nested table, varray) EXISTS 이외의 메소드를

사용했을 때 발생되는 예외.

 

- 예외명: CURSOR_ALREADY_OPEN

예외번호: ORA-06511

설명: 이미 열려진 커서를 열려고 시도 했을 때 발생되는 예외.

 

- 예외명: DUP_VAL_ON_INDEX

예외번호: ORA-00001

설명: 유일인덱스에 중복값을 입력했을 경우 발생되는 예외.

 

- 예외명: INVALID_CURSOR

예외번호: ORA-01001

설명: 잘못된 커서 조작이 실행될 때 발생되는 예외.

 

- 예외명: INVALID_NUMBER

예외번호: ORA-01722

설명: 문자를 숫자로의 변환 시 실패가 될 때 발생되는 예외.

 

예외명: LOGIN_DENIED

예외번호: ORA-01017

설명: 잘못된 사용자명 이나 암호로 로그인을 시도했을 때 발생되는 예외.

 

예외명: NO_DATA_FOUND

예외번호: ORA-01403

설명: PL/SQL SELECT 문이 한 건도 리턴 하지 못했을 경우 발생하는 예외

 

예외명: NOT_LOGGED_ON

예외번호: ORA-01012

설명: 접속되지 않은 상태에서 데이터베이스에 대한 요청이 PL/SQL 프로그램으로 실행된 경우 발생되는 예외.

 

예외명: PROGRAM_ERROR

예외번호: ORA-06501

설명: PL/SQL 이 내부적인 문제를 가지고 있는 경우 발생되는 예외

 

예외명: ROWTYPE_MISMATCH

예외번호: ORA-06504

설명: 할당문에서 호스트 커서 변수와 PL/SQL 커서 변수의 데이터 형이 불일치 할 때 발생되는예외

 

예외명: STORAGE_ERROR

예외번호: ORA-06500

설명: PL/SQL 이 실행될 때 메모리가 부족하거나 메모리상에 문제가 일어났을 때 발생하는 예외

 

예외명: SUBSCRIPT_BEYOND_COUNT

예외번호: ORA-06533

설명: 컬렉션의 요소 개수보다 더 큰 첨자 값으로 참조한 경우 발생되는 예외.

 

예외명: SUBSCRIPT_OUTSIDE_LIMIT

예외번호: ORA-06532

설명: 컬렉션의 첨자의 한계를 벗어난 참조가 일어났을 때 발생되는 예외

 

예외명: SYS_INVALID_ROWID

예외번호: ORA-01410

설명: 문자열을 ROWID 로 변환할 때 무효한 문자열의 표현일 경우 발생되는 예외

 

예외명: TIMEOUT_ON_RESOURCE

예외번호: ORA-00051

설명: 자원에 대한 대기시간이 초과했을 때 발생하는 예외

 

예외명: TOO_MANY_ROWS

예외번호: ORA-01422

설명: PL/SQL SELECT 문이 두 건 이상의 행을 리턴 했을 때 발생되는 예외

 

예외명: VALUE_ERROR

예외번호: ORA-06502

설명: 산술, 변환, 절삭 또는 크기 제약에 에러가 생겼을 때 발생되는 예외

 

예외명: ZERO_DIVIDE

예외번호: ORA-01476

설명: 0으로 나누려 했을 때 발생하는 예외.

 

2. PL/SQL 블록내의 예외 처리부

EXCEPTION
WHEN exception1 [OR exception2 …] THEN
    statement1 ;
    statement2 ;
…
[ WHEN exception3 [OR exception4 …] THEN
    statement3 ;
    statement4 ;
… ]
[WHEN OTHERS THEN
    statementN ;
    statementN+1 ;
… ]

예외처리 사용 예 1: 오라클에서 사전 정의된 예외 처리하기

 

사원명이 ‘B’ 로 시작하는 사원을 조회하는 하되 여러 건의 데이터가 나올 경우 에러를 발생시키는 예외 처리부분을 포함하세요

HR> SELECT first_name

2 FROM employees

3 WHERE first_name LIKE 'B%';

 

FIRST_NAME

--------------------

Bruce

Britney ---> B 로 시작하는 사원이 2명 검색됩니다.

 

declare
    v_fname employees.first_name%TYPE;
begin
    select first_name into v_fname
    from employees
    where first_name like 'B%';
    DBMS_OUTPUT.PUT_LINE ('사원명은'||v_fname||' 입니다');
end;

exception없이 실행시킬 경우

v_fname에는 두 명의 이름이 들어갈 수 없으므로 에러가 남

 -> 덮어 쓸 수는 있는데 DBMS로 표현은 1번만 함 -> 오류!

오류 보고 -
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 4
01422. 00000 -  "exact fetch returns more than requested number of rows"
*Cause:    The number specified in exact fetch is less than the rows returned.
*Action:   Rewrite the query or change number of rows requested

2건의 데이터를 커서에 넣으려면 명시적 커서를 선언하고 사용해야 하는데 묵시적 커서를 쓰게 하여

에러를 발생시켜 예외처리 실습

 

EXCEPTION 없이 실행 시키면 에러가 남!

- 실제로는 리부팅 이런 것들을 많이 함

기본키인 no에 1을 또 삽입하려고 해서 난 에러 -> 기본키 오류

- 개체 무결성

- 오류 해결 안됨 -> PL/SQL에서 exception으로 처리

 

- PRAGMA : 전처리(Pre processing) 

                (본)처리 - 요게 우리가 주로 하는 것

                후처리

declare
    new_msg exception;  -> new_msg라는 변수를 exception이라는 자료형으로 만든다.
    pragma exception_init(new_msg, -1);  -- exception_init 함수이름 : 초기화(new_msg, -1) -> new_msg라는 오류를 1번으로 하겠다.
Begin
    insert into t_pragma VALUES(1, 'CCC'); -- 이미 1에 AAA가 있으므로 에러가 남
Exception
    when new_msg then                      -- new_msg가 에러가 나면(1이 에러가 나면) exception
    dbms_output.put_line('존재하는 번호입니다!');  -- 이걸 출력하라
END ;    

-- 1번 에러 : new_msg
-- 키본기 에러 따로 있음

 

 

- 예외 처리 사용 예 3: RAISE 를 사용하여 예외 처리하기

employee_id 를 입력 받은 후 employees 테이블에서 해당 사원을 지우는 작업을 수행합니다. 단 없는 사원번호를 입력할 경우 사원이 없습니다라는 예외 메시지를 출력하게 만듭니다.

HR>CREATE TABLE employees11

2 AS                                        -- 복제

3 SELECT employee_id , first_name

4 FROM employees ;

  -> 실습 해보는 거니까 원본 테이블에서 실제로 사원이 삭제가 되면 안되므로!! 복제 테이블인 employees11을 만든다.

RAISE : 발생시키다 -> 오류를 발생시킨다

 

declare
    no_empid exception;         -- 자료형이 exception인 no_empid 선언
begin
    delete from employees11
    where employee_id =&empid;  -- id를 입력 받아서 해당하는 것을 employees11에서 지울 것
        if SQL%NOTFOUND THEN    -- 묵시적커서 : 데이터가 없을 경우에(지울게 없을 경우에) 결과값 자체가 없다면
            RAISE no_empid ;    -- no_empid라는 에러를 발생시킨다.
        END IF;
exception
    WHEN no_empid then          -- no_empid라는 에러가 발생하면
        DBMS_OUTPUT.PUT_LINE('입력하신 번호는 없는 사원번호 입니다.');  -- 이걸 출력한다.
end;    

 

 

- 예외 처리 사용 예 4 : RAISE_APPLICATION_ERROR 프로시저 사용하기

RAISE_APPLICATION_ERROR 프로시저를 사용하여 사용자가 에러를 정의하고

즉시 예외를 처리하는 방식입니다.

이때 사용 가능한 에러 번호는 20000 번부터 20999 번 까지 입니다.

begin
    delete from employees11
    where employee_id =&empid;   -- 결과없음이 나올 때
        if sql%notfound then
            raise_application_error(-20100, '입력하신 번호는 없는 사원번호 입니다');  --이걸 출력
        End if;
END;        

-- raise_application_error(-20100, '블라블라') -> 20100번을 에러로 지정하겠다.

--결과
ORA-20100: 입력하신 번호는 없는 사원번호 입니다  -- 이렇게 실제 오라클에서 나오는 에러처럼 표시해줌

 

 


8장. INDEX(인덱스)

1. 인덱스(INDEX)란 무엇일까요?

 - 목적 : 빠른 검색

 - 누군가를 찾고싶은데 빨리 찾기 위해서는 책상 번호대로 A, B, C 순으로 앉으면 좋은데

   실제로는 그렇지 않음..

   -> 그래서 A, B, C 순으로 임의로 번호 부여

   -> A B C 순으로 오름차순 정렬을 해서

       ALLEN을 1번으로, BLAKE를 2번으로, CLARK를 3번으로... 인덱스 지정

 

 

2. 인덱스의 생성 원리

3. 인덱스 구조와 작동 원리(B-TREE 인덱스 기준)

-> B-TREE 구조

 

인덱스 1, 2, 3을 7로 묶고

          4, 5, 6을 8로 묶음   -> 7, 8을 9로 묶음

 

검색 시 G이면 8 -> 4 -> 4 이렇게 가서 G를 찾음

 

4. 인덱스의 종류

1) B-TREE 인덱스


다음 시간에 UNIQUE INDEX부터 할 것

728x90
728x90