반응형

컴파일 에러 - PL/SQL 블록이 PARSE 되는 동안 오타 등으로 인해 발생되는 에러

런타임 에러 - PL/SQL 블록이 실행되는 동안에 발생되는 에러, 이 런타임 에러를 오라클에서 예외라고 부름


오라클의 예외 종류 - 오라클에서 미리 제공하는 오라클 예외

   - 사용자에 의해 정의되는 사용자 정의 예외


오라클 예외 : 오라클이 정의한 상황에서 자동적으로 발생 

- 이름이 정해진 예외 : Predefined ORACLE Exception

- 이름이 정해지지 않은 예외 : Non-predefined ORACLE Exception


사용자 정의 예외 : 선언부에서 exception 형으로 예외를 선언한 후 실행부 또는 예외처리부에서 RAISE문을 통해 

  명시적으로 예외 발생


예외 처리 사용하기

예외를 처리하기 위해서 PL/SQL 블록에는 예외처리부(EXCEPTION) 라는 부분이 있는데 이부분에 처리문장을 적으면 됨


문법 : 

EXCEPTION

WHEN exception1 [OR exception2 ...] THEN

statement1 ;

statement2 ;

....

[WHEN exception3 [OR exception4 ...] THEN

statement3 ;

statement4 ;

... ]

[WHEN OTHERS THEN

statementN ;

statementN+1 ;

... ]


- exception N

실행부에서 발생한 예외의 이름들로 해당되는 WHEN 절 안의 문장들을 수행


- OTHERS 

이전의 WHEN 에 해당하는 예외를 처리하지 않고 가장 마지막에 기술되는 WHEN 에 해당하는 예외 만 사용



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

사원명이 'A' 로 시작하는 사원을 조회하여 묵시적 커서를 사용하여 출력하되 여러 건의 데이터가 나올 경우 에러발생하는 예외처리 생성


SQL>SELECT ename

FROM emp

WHERE ename LIKE 'A%' ;


-> ENAME

    -------

ALLEN

ADAMS    -- A 로 시작하는 사원 2명 검색


사원의 데이터가 2인데 명시적 커서를 사용해 PL/SQL을 사용해야 하지만 묵시적 커서를 사용하여 TOO_MANY_ROWS 라는 예외가 발생, 이 경우 예외 처리 기능을 사용하여 보다 좋게 처리 하는 예


SQL>DECLARE

v_ename    emp.ename%TYPE ;

BEGIN

SELECT ename    INTO v_ename

FROM emp

WHERE ename LIKE 'A%' ;

DBMS_OUTPUT.PUT_LINE ('사원명은'||v_ename||' 입니다') ;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE(' 해당 사원이 없습니다') ;

WHEN TOO_MANY_ROWS THEN

DBMS_OUTPUT.PUT_LINE(' 사원이 두 명 이상입니다') ;

END ;

/

Enter value for dno : 10

해당 부서에 사원이 존재하므로 삭제할 수 없습니다


위에 굵은 글자가 예외 처리 부 이며 위와 같이 발생시킬 예외들을 지정해 주면 됨


예외처리 사용 예 2 : PRAGMA 를 사용하여 에러메시지 변경하기

PRAGMA 란 키워드는 특정 에러코드와 예외 메시지를 연결해주는 역할


두 개의 테이블이 서로 Foreign Key 가 설정되어 있는 상태에서 부모테이블에서 부서 번호를 입력 받아 해당 부서를 삭제하되 자식 테이블에 해당 부서에 소속된 사원이 있을 경우 '해당 부서에 사원이 존재하므로 삭제할 수 없습니다 ' 라는 예외를 발생시키는 예제.


SQL> DECLARE

2        sawon_exist EXCEPTION ;

3        PRAGMA EXCEPTION_INIT(sawon_exist,-2292) ;

4    BEGIN

5        DELETE FROM dept

6        WHERE deptno=&dno ;

7        COMMIT ;

8    EXCEPTION

9        WHEN sawon_exist THEN

10      DBMS_OUTPUT.PUT_LINE('해당 부서에 사원이 존재하므로 삭제할 수 없습니다') ;

11  END ;

12   /


-> PRAGMA EXCEPTION_INIT는 컴파일러에게 예외 이름을 Oracle 오류 번호와 연관시키도록 지시

이렇게 하면 모든 내부 예외를 이름으로 참조하고 이 예외에 대한 특정 처리기를 작성

3 번째 줄 끝에 -2292 는 에러 발생시 나오는 오라클 에러 번호



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

아래의 예는 empno 를 입력 받은 후 emp 테이블에서 해당 사원을 지우는 작업을 수행

단, 없는 사원번호를 입력할 경우 '사원이 없습니다' 라는 예외 메시지 출력


SQL> DECLARE

no_empno EXCEPTION ;

   BEGIN

DELETE FROM EMP

WHERE empno = &empno ;

IF SQL%NOTFOUND THEN

RAIS no_empno ;

END IF ;

   EXCEPTION   

WHEN no_empno THEN

DBMS_OUTPUT.PUT_LINE('조회한 사번의 사원은 없습니다') ;

   END ;

          /

   Enter value for empno : 7901

   조회한 사번의 사원은 없습니다

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

앞에서 사용한 3가지 예는 모두 예외 처리부에서 각각의 예외를 처리하는 방식

지금 살펴보는 예는 RAISE_APPLICATION_ERROR 프로시저를 사용하여 사용자가 특정 상황에 발생할 에러를 정의하고 예외 처리부를 사용하지 않고 실행부에서 즉시 예외처리 하는 방식.

이때 사용자가 임의로 지정 가능한 에러번호는 20000 ~ 20999 번 까지


SCOTT> SET VERIFY OFF

SCOTT> BEGIN

DELETE FROM emp WHERE empno = &empno ;

IF SQL%NOTFOUND THEN

RAISE_APPLICATION_ERROR(-20001, '존재하지 않는 사번입니다') ;

END IF ;

END ;

/

Enter value for empno : 7901

BEGIN

*

ERROR at line 1 :

ORA-20001 : 존재하지 않는 사번입니다

ORA-06512 : at line 4


4번 라인에 RAISE_APPLICATION_ERROR 프로시저를 사용하여 에러메시지를 정의.

위 에러 부분을 보면 RAISE_APPLICATION_ERROR 프로시저에 기록된 에러메시지가 보이는 것을 확인 할 수 있다


예외처리 사용 예 5: SQLCODE 와 SQLERRM 사용하기

어떤 에러가 발생했는지 확인하기위해 SQLCODE 와 SQLERRM 을 사용

아래 예는 사용자로부터 empno 를 입력받아서 해당 empno 의 ename을 화면에 출력하는 코드

이 때 사용자가 없는 empno 를 입력할 경우 발생하는 Error code 와 Error 내용을 확인하기 위해 SQLCODE 와 SQLERRM을 사용


SCOTT>SET VERIFY OFF

SCOTT>DECLARE

name    emp.ename%TYPE ;

v_code    NUMBER ;

v_errm    VARCHAR2(64) ;

BEGIN

SELECT ename INTO name FROM emp WHERE empno = &eno ;

 EXCEPTION

   WHEN OTHERS THEN

v_code := SQLCODE ;

v_errm := SUBSTR(SQLERRM,1,64) ;

DBMS_OUTPUT.PUT_LINE('The error code is '||v_code||'-'||v_errm) ;

END ;

/

Enter value for eno : 7902

-> 존재하는 empno 라서 에러가 생기지 않음


SCOTT>/

Enter value for eno : 7900

The error code is 100-ORA-01403:no data found   <-- 존재하지 않는 번호라서 에러 발생


반응형

'오라클 > PL/SQL' 카테고리의 다른 글

PL/SQL sub program  (0) 2014.10.16
PL/SQL CURSOR  (0) 2014.10.14
PL/SQL 제어문  (0) 2014.10.13
PL/SQL 변수  (0) 2014.10.13
PL/SQL 시작하기  (0) 2014.10.13
반응형

커서 - 묵시적 커서(Implicit Cusor) : 필요할 경우 오라클이 자동적으로 선언하여 사용한 후 자동적으로 정리

 - 명시적 커서(Explicit Cursor) : 사용자가 정의한 커서른 선언하여 사용하고, 커서의 사용이 끝난 후에는 별도의 정리                                                작업을 수행해줘야 함



묵시적 커서

- 세션 내에 단 한 개만이 선언되어 사용되었다가 문장이 종료됨과 동시에 정리, 1개의 데이터만 저장됨


묵시적 커서 속성

- SQL%ROWCOUNT

해당 커서에서 실행한 총 행의 개수(가장 마지막 행이 몇 번째 행인지 카운트)를 반환


- SQL%FOUND

해당 커서 안에 아직 수행해야 할 데이터가 있을 경우 TRUE 값을 반환하고 없을경우 FALSE 값을 반환


- SQL%NOTFOUND

해당 커서 안에 아직 수행해야 할 데이터가 없을 경우 TRUE 값을 반환하고 있을경우 FALSE 값을 반환


- SQL%ISOPEN

현재 묵시적 커서가 메모리에 OPEN 되어 있을 경우에는 TRUE 값을, 그렇지 않을 경우 FALSE 값을 가지는 속성


사용 예)


SCOTT>DECLARE

BEGIN

DELETE emp

WHERE sal < 1000 ;

DBMS_OUTPUT.PUT_LINE('1000 이하 : '||sql%rowcount||'건 삭제되었습니다') ;

DELETE emp

WHERE sal BETWEEN 1000 AND 2000 ;

DBMS_OUTPUT.PUT_LINE('1000~2000 사이 : '||sql%rowcount||'건 삭제 되었습니다') ;

END ;

/


-> 1000 이하 : 2 건 삭제 되었습니다

     1000 ~2000 사이 : 6 건 삭제 되었습니다


명시적 커서

사용자가 선언하여 생성 후 사용하는 SQL 커서로, 여러 개의 행을 처리하고자 할 경우 사용


명시적 커서 속성

- 커서이름%ROWCOUNT

FETCH 문에 의해 읽혀진 데이터의 총 행 수를 가지는 속성. 가장 마지막에 처리된 행이 몇 번째 인지 반환

- 커서이름%FOUND

FETCH 문이 수행되었을 경우, 읽혀진(FETCH) 행이 있을 경우에는 TRUE 값을, 그렇지 않을 경우 FALSE 값을 가짐

- 커서이름%NOTFOUND

FETCH 문이 수행되었을 경우, 읽혀진(FETCH) 행이 없을 경우에는 TRUE 값을, 그렇지 않을 경우 FALSE 값을 가짐

- 커서이름%ISOPEN

명시적 커서가 메모리에 확보(선언) 되어 있을 경우에는 TRUE 값을, 그렇지 않을 경우에는 FALSE 값을 가짐


묵시적 커서와 FOR LOOP 문 활용하기

      

SCOTT>DECLARE

BEGIN

DBMS_OUTPUT.PUT_LINE('학과명과 학과의 위치 안내 입니다') ;

DBMS_OUTPUT.PUT_LINE('---------------------------------') ;

FOR dept_cur IN (SELECT dname,build

                                     FROM department 

                   WHERE build IS NOT NULL

 ORDER BY 1)

LOOP

DBMS_OUTPUT.PUT_LINE(dept_cur.dname||'-->'||dept_cur.build||'에 있습니다') ;

END LOOP ;

END ;

/


-> 학과명과 학과의 위치 안내 입니다

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

기계공학과 --> 기계실험관 에 있습니다

멀티미디어공학과 --> 멀티미디어관 에 있습니다

문헌정보학과 --> 인문관 에 있습니다

.... 


명시적 커서 처리 단계

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

PL/SQL의 선언부(DECLARE)에 다른 변수와 마찬가지로 선언되어야 하며, 형식은 아래와 같다

- 문법 :

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

- 커서명 : 명시적 커서의 이름

- 서브쿼리 : 처리하고자 하는 데이터를 검색하는 SELECT 문장을 이부분에 기술


2) 명시적 커서 오픈(OPEN)

선언 시 기술했던 서브쿼리를 수행해서 데이터를 커서로 가져 온다는 뜻. 

- 문법 :

OPEN 커서 이름 ;

- 커서이름 : 열고자 하는 명시적 커서의 이름


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

명시적 커서의 데이터들로부터 데이터를 한 건씩 읽어 변수로 할당하기 위해 FETCH문을 사용

- 문법 :

FETCH 커서 이름 INTO 변수

- 커서이름 : 읽어(FETCH) 오고자 하는 명시적 커서의 이름으로 반드시 OPEN 되어 있어야 FETCH 가능

- 변수들 : 명시적 커서로부터 읽어온(FETCH) 데이터 행(레코드) 을 PL/SQL 블록 내에서 처리하기 위해서   

               변수에 저장해서 사용. 


4) 명시적 커서 닫기(CLOSE)

명시적 커서의 정리 작업을 하는 명령으로, 명시적 커서가 다 사용된 후에는 반드시 '닫기'를 해야 함.

커서를 닫는다 함은 작업이 끝난 메모리 공간을 반환하고 정리한다는 뜻

- 문법 :

CLOSE 커서 이름 ;

- 커서이름 : 닫고자 하는 명시적 커서의 이름으로 Close 된 명시적 커서는 더 이상 사용하지 않는다


사용 예)

SCOTT>DECLARE

vempno NUMBER(4) ;

vename VARCHAR2(20) ;

vsal NUMBER(7) ;


     (커서 선언)     CURSOR c1 IS

      SELECT empno, ename, sal

            FROM emp

      WHERE deptno=20 ;

           

BEGIN

     (커서 오픈)    OPEN c1 ;

            DBMS_OUTPUT.PUT_LINE('번호 이름  급여') ;

          

LOOP

    (데이터 추출)  FETCH c1 INTO vempno, vename, vsal ;

            EXIT WHEN c1%NOTFOUND ;

         

DBMS_OUTPUT.PUT_LINE(vempno||'  '||vename||' '||vsal) ;

            END LOOP ;

     (커서 닫기)    CLOSE c1 ;

      END ;

/



명시적 커서와 Cursor FOR LOOP 문 활용

문법 :

FOR record_name IN cursor_name LOOP

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

statement1 ;

statement2 ;

....

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


- record_name 커서로부터 FETCH 된 하나의 레코드를 저장하기 위한 커서 레코드 변수, 자동으로 만들어짐

- cursor_name : 처리하고자 하는 명시적 커서명으로, 선언부에서 정의되어야 함. 


명시적 CURSOR 와 CURSOR FOR LOOP 문 사용 예 :

emp 테이블에서 empno, ename 값을 가져와서 커서에 저장 후 출력하세요.


SCOTT>DECLARE

 CURSOR emp_cur IS   -- 커서 선언

       SELECT empno, ename

       FROM emp ;

    BEGIN

       FOR emp_rec IN emp_cur      -- 커서의 데이터를 저장할 emp_rec 변수 선언

        LOOP

          DBMS_OUTPUT.PUT_LINE(emp_rec.empno||' '||emp_rec.ename) ;

        END LOOP ;

    END ;

  /


파라미터 Explicit Cursor

- 명시적 커서를 선언 한 후 OPEN 할 때 값을 바꾸어서 수행해야 할 경우, 커서를 OPEN 할 때 필요한 값만 파라미터로 

전달해서 반복 수행 할 수 있는 방법

문법 :

CURSOR cursor_name

[(parameter_name dataTYPE ,...)] 

IS select-statement ;


- parameter_name : 파라미터 변수명으로 변수선언과 동일하며 여러 개의 파라미터를 지정할 수 있다


파라미터 Explicit Cursor 사용 예 :

SCOTT>DECLARE

CURSOR prof_cur (v_deptno IN NUMBER)

IS SELECT *

FROM professor

WHERE deptno=v_deptno ;

v_prof professor%ROWTYPE ;

BEGIN

DBMS_OUTPUT.PUT_LINE('============================') ;

DBMS_OUTPUT.PUT_LINE('101번 학과 교수님 번호와 이름 출력') ;

DBMS_OUTPUT.PUT_LINE('----------------------------') ;

OPEN prof_cur(101) ;

LOOP

FETCH prof_cur INTO v_prof ;

EXIT WHEN prof_cur%NOTFOUND ;

DBMS_OUTPUT.PUT_LINE(v_prof.profno||' 번 교수님 이름은 '||v_prof.name||' 입니다') ;

END LOOP ;

CLOSE prof_cur ;

DBMS_OUTPUT.PUT_LINE('============================') ;

DBMS_OUTPUT.PUT_LINE('102번 학과 교수님 번호와 이름 출력') ;

DBMS_OUTPUT.PUT_LINE('----------------------------') ;

OPEN prof_cur(102) ;

LOOP   

FETCH prof_cur INTO v_prof ;

EXIT WHEN prof_cur%NOTFOUND ;

DBMS_OUTPUT.PUT_LINE(v_prof.profno||' 번 교수님 이름은 '||v_prof.name||' 입니다') ;

END LOOP ;

CLOSE prof_cur ;

END ;

/


Cursor 와 Select....FOR UPDATE 문장

명시적 커서를 선언해 데이터를 조회한 후 변경을 하려는 중에 다른 세션에서 현 세션이 작업하는 내용을 변경 할 수 있다.

예를 들어 조회 할 시점에 A라는 데이터였지만 조회나 변경하는 중에 다른 세션이 B 라는 데이터로 바꿀수 있다는 뜻

그래서 커서를 선언 할 때 커서에 있는 행들에 대해 잠금을 수행.


1) 기본 문법 

이 실습을 위해 두 개의 세션에서 작업 실행


-세션 1-                                                                    -세션 2-

SCOTT>SELECT empno,ename,sal                                SCOTT>UPDATE emp

FROM emp                                                                  SET sal = 1000

WHERE empno = 7900                                                  WHERE empno = 7900 ;

FOR update ;                                                    -> 대기 상태로 반응 없습니다.


EMPNO    ENAME    SAL

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

    7900     JAMES    950

위와 같이 세션 1 에서 select 구문에 for update를 함께 쓰면 해당 데이터에 lock이 설정되어 다른 세션에서 dml 작업을 할 경우 대기상태로 들어감.

이 상태에서 세션 1 에서 commit 이나 rollback 명령을 수행하면 세션 2 에서 작업이 진행됨


2) Cursor 에서 SELECT... FOR update 사용하기

문법 :

SELECT ...

FROM ...

FOR UPDATE [OF column_reference][NOWAIT|WAIT n] ;


위 옵션중 NOWAIT 옵션은 다른 세션에서 행을 잠글 경우 즉시 오라클 에러를 발생 시켜주는 옵션.

다른 세션에서 해당 행에 LOCK 을 설정했을 경우 NOWAIT 옵션을 사용하면 즉시 에러를 발생시킴

그러나 만약 NOWAIT 옵션을 사용하지 않을 경우 LOCK 이 확보 될 때 까지 무한 대기상태

WAIT n = n자리에 초를 설정할 수 있으며 해당 초가 지난 후에도 LOCK을 확보할 수 없으며 에러발생


Cursor 에서 FOR UPDATE 구문 사용 예 :

DECLARE

CURSOR emp_cur IS

SELECT empno, ename, sal

FROM emp

WHERE deptno = 20

FOR UPDATE     -- 커서 선언시에 FOR UPDATE 로 행을 잠금

NO WAIT ;

....

BEGIN

....

OPEN emp_cur ;

....

UPDATE emp

SET sal = sal * 2

WHERE CURRENT OF emp_cur          -- 커서 선언 시에 잠긴 행 갱신

....

CLOSE emp_cur ;

END ;


반응형

'오라클 > PL/SQL' 카테고리의 다른 글

PL/SQL sub program  (0) 2014.10.16
PL/SQL 예외처리  (0) 2014.10.16
PL/SQL 제어문  (0) 2014.10.13
PL/SQL 변수  (0) 2014.10.13
PL/SQL 시작하기  (0) 2014.10.13
반응형

1. 조건문 (IF 문)

유형 1. IF ~ END IF 문장

조건이 여러 개 일 경우에 사용하는 가장 기본적인 IF 문장

문법 : 

IF (조건) THEN

실행문장 ;

END IF ;

예 : EMP 테이블에서 EMPNO, ENAME, DEPTNO, DNAME 을 출력

단 DNAME 의 값은 아래와 같다

DEPTNO 가 10 이면 'ACCOUNT' ,

DEPTNO 가 20 이면 'RESEARCH' ,

DEPTNO 가 30 이면 'SALES' ,

DEPTNO 가 40 이면 'OPERATIONS' 로 출력


SCOTT>DECLARE

vempno emp.empno%TYPE ;

vname emp.ename%TYPE ;

vdeptno emp.deptno%TYPE ;

vdname VARCHAR2(20) := null ;

BEGIN

SELECT empno, ename, deptno

INTO vempno, vename, vdeptno

FROM emp

WHERE empno=7900 ;

IF (vdeptno = 10) THEN  --IF 문 시작

vdname :='ACCOUNT' ;

END IF ; --IF 문 끝

IF (vdeptno = 10) THEN

vdname :='RESEARCH' ;

END IF ;

IF (vdeptno = 10) THEN

vdname :='SALES' ; 

END IF ;

IF (vdeptno = 10) THEN

vdname :='OPERATIONS' ;

END IF ;

DBMS_OUTPUT.PUT_LINE (vempno||'  '||vename||'  '||vdeptno||'  'vdname) ;

END ;

/


위처럼 조건이 여러 개 일 경우 매번 조건을 새로 시작해야 하기에 사용함에 있어 불편함이 많다.

그래서 조건이 2개 이상일 경우 다음의 유형 2의 방법을 더 많이 사용


유형 2.IF ~THEN ~ELSIF ~END IF 문장

문법 :

IF (조건) THEN

실행문장 ;

   ELSIF (조건) THEN

실행문장 ;

   ELSIF (조건) THEN

실행문장 ;

END IF ;

예 : MP 테이블에서 EMPNO, ENAME, DEPTNO, DNAME 을 출력

단 DNAME 의 값은 아래와 같다

DEPTNO 가 10 이면 'ACCOUNT' ,

DEPTNO 가 20 이면 'RESEARCH' ,

DEPTNO 가 30 이면 'SALES' ,

DEPTNO 가 40 이면 'OPERATIONS' 로 출력


SCOTT>DECLARE

vempno emp.empno%TYPE ;

vname emp.ename%TYPE ;

vdeptno emp.deptno%TYPE ;

vdname VARCHAR2(20) := null ;

BEGIN

SELECT empno, ename, deptno

INTO vempno, vename, vdeptno

FROM emp

WHERE empno=7900 ;

IF (vdeptno = 10) THEN

vdname :='ACCOUNT' ;

ELSIF (vdeptno = 20) THEN

vdname :='RESEARCH' ;

ELSIF (vdeptno = 30) THEN

vdname :='SALES' ;

ELSIF (vdeptno = 40) THEN

vdname :='OPERATIONS' ;

END IF ;
DBMS_OUTPUT.PUT_LINE (vempno||'  '||vename||'  '||vdeptno||'  '||vdname) ;
END ;
/
유형 3.IF~THEN~ELSE~END IF (조건이 2개 일 경우 사용)
비교조건이 2개 일 경우 사용되는 IF 문장
문법 :
IF (조건) THEN
실행 문장 ;
ELSE
실행 문장 ;
END IF ;

예 : EMP 테이블에서 사원번호가 7900 번인 사원의 EMPNO, ENAME, COMM 을 출력하되 해당 사원의 COMM 이 0보다 크면 COMM 의 금액을 출력하고, 0 보다 작으면 '사원의 보너스는 없습니다' 라는 문장을 출력

SCOTT>DECLARE
vempno    emp.empno%TYPE ;
vename    emp.ename%TYPE ;
vcomm    emp.comm%TYPE :=NULL ;
BEGIN
SELECT empno, ename, comm INTO vempno, vename, vcomm
FROM emp
WHERE empno = 7900 ;
IF vcomm >0 THEN
DBMS_OUTPUT.PUT_LINE (vename||' 사원의 보너스는 '||vcomm||'입니다') ;
ELSE    
DBMS_OUTPUT.PUT_LINE (vename||' 사원의 보너스는 없습니다') ;
END IF ;
END ;
/

2. CASE 문

IF 문장과 같이 비교 조건이 여러 가지 일 경우 훨씬 더 간결하고 간단하게 조건을 파악해서 분기시킬 수 있는 제어문

문법 :

CASE [조건]

WHEN 조건 1 THEN 결과 1

WHEN 조건 2 THEN 결과 2

...

WHEN 조건 n THEN 결과 n

[ELSE 기본값]

END ;


CASE 내부의 여러 조건들을 구분할 때 ,(콤마) 를 사용하지 않음


사용 예 1 : 사용자로부터 사원 번호를 입력 받은 후 EMP 테이블에서 EMPNO, ENAME, DEPTNO, DNAME 을 출력하되

     DEPTNO 가 10 이면 'ACCOUNT' ,

     DEPTNO 가 20 이면 'RESEARCH' ,

     DEPTNO 가 30 이면 'SALES' ,

     DEPTNO 가 40 이면 'OPERATIONS' 로 출력


SCOTT>DECLARE

2    v_empno    emp.empno%TYPE ;

3    v_ename    emp.ename%TYPE ;

4    v_deptno    emp.deptno%TYPE ;

5    v_dname    varchar2(10) ;

6    BEGIN

7    SELECT empno, ename, deptno

8    INTO    v_empno, v_ename, v_deptno

9    FROM emp

10   WHERE empno = &empno ;

11   v_dname := CASE v_deptno

12                     WHEN 10 THEN 'ACCOUNT'

13                     WHEN 20 THEN 'RESEARCH'

14                     WHEN 30 THEN 'SALES'

15                     WHEN 40 THEN 'OPERATIONS'

16                    END ;

17    DBMS_OUTPUT.PUT_LINE (v_empno||'  '||v_deptno||'  'v_dname) ;

18    END ;

19    /

Enter value for empno : 7900

7900    JAMES    30    SALES


위 예에서 11~ 16줄의 CASE 부분을 아래와 같이 변형해도 결과는 동이랗게 나옴

11    v_dname := CASE

12                        WHEN v_deptno = 10 THEN 'ACCOUNT'

13                        WHEN v_deptno = 20 THEN 'RESEARCH'

14                        WHEN v_deptno = 30 THEN 'SALES'

15                        WHEN v_deptno = 40 THEN 'OPERATIONS'

16                       END ;









3. 반복문


반응형

'오라클 > PL/SQL' 카테고리의 다른 글

PL/SQL sub program  (0) 2014.10.16
PL/SQL 예외처리  (0) 2014.10.16
PL/SQL CURSOR  (0) 2014.10.14
PL/SQL 변수  (0) 2014.10.13
PL/SQL 시작하기  (0) 2014.10.13
반응형

PL/SQL 에서 변수를 사용하는 이유

- 변수는 데이터의 임시 저장 영역이다.

- 저장된 값을 조작하기 위해 사용

- 저장된 값을 반복해서 재 사용할 수 있다.


PL/SQL 에서 사용될 변수의 규칙 

- 반드시 문자로 시작해야만 한다.

- 문자나 숫자, 특수문자를 포함할 수 있다.

- 변수명은 30 bytes 이하여야 한다.

- 예약어를 포함하면 안된다


주요 변수들의 종류


단순 변수

-Scalar(스칼라) 변수 와 Reference 변수

Scalar 변수 - 단일 값을 가지는 변수의 데이터 형을 직접 지정해 주는 변수, 즉 정수, 실수 이런 형태를 직접 지정

Reference 변수 - 데이터 형을 다른 컬럼에서 참조 후 지정하는 방식


(1) Scalar 변수

문법 : Identifier [CONSTANT] datatype [NOT NULL] [:=|DEFAULT expr] ;


- Identifier : 변수의 이름으로 다른 변수와 구별되는 식별자의 역할을 하며 블록 내에서는 유일해야 한다.


- CONSTANT : 읽기전용 변수, 즉 상수로 선언하기 위한 키워드로 기본적으로 초기값이 반드시 지정되어야 한다.

    (값이 없을 경우 생략 가능) 예. V_RATE CONSTANT NUMBER := 0.2 ; 


- Datatype : 오라클에서 허용하는 데이터 타입은 모드 지원 

- %TYPE 을 사용하여 테이블내의 컬럼과 동일한 데이터 형을 선언할 수 있음

- %ROWTYPE 을 사용하여 테이블의 레코드 구조와 동일 형태의 레코드를 선언할 수 있음


- NOT NULL : 항상 값을 가지도록 제약을 주는 키워드로 이 값을 줄 경우 초기값이 반드시 지정되어야 하며 없을 경우                      생략 가능    예.V_NAME VARCHAR2(14) NOT NULL := '이순신' ;


- := 또는 DEFAULT : 변수에 기본값을 할당하기 위한 키워드   예. V_DATE DATE DEFAULT SYSDATE ;


- expr : 변수에 부여할 기본값을 의미하며 단순한 ㄱ밧에서부터 다른 변수, 수식, 함수가 올 수 있다.


주요 스칼라 변수 선언 예


Vno number(5,3) <- 숫자를 저장하는 변수로 총 5자리이며 소수점이하 3자리를 의미

Vname varchar2(10) <- 문자를 저장하는 변수로 총 10바이트의 길이를 저장할 수 있다

Vday date <- 날짜를 저장하는 변수


(2) 주요 Scalar 변수의 데이터 타입

- CHAR[(최대길이)] : 고정 길이의 문자를 저장하며 최대 32,767 바이트 값을 저장. 기본 최소값=1


- VARCHAR2 (최대길이) : 가변 길이의 문자를 저장하며 최대 32,767 바이트 값을 저장. 기본값 X


- NUMBER [(전체자리수, 소수점이하 자리수)] : 전체 자리수와 소수점 이하의 자리수를 가진 숫자

 전체 자리수의 범위는 1부터 38까지, 소수점 이하 자리수 범위는 -84 부터 127 까지


- BINARY_INTEGERR : -2,147,483,647 ~ 2,147,483,647 사이의 정수를 저장하는 타입


- PLS_INTERGER : -2,147,483,647 ~ 2,147,483,647 사이의 부호 있는 정수에 대한 기본 유형

NUMBER 값보다 저장 공간이 적게 필요하고 연산 속도가 더 빠름


- BOOLEAN : 논리적 계산에 사용 가능한 세 가지 값(TRUE, FALSE, NULL) 중 하나를 저장하는 기본 유형


- BINARY_FLOAT : IEEE 754 형식의 부동 소수점 수를 나타냄. 값을 저장하기 위해 5바이트가 필요


- BINARY_DOUBLEIEEE 754 형식의 부동 소수점 수를 나타냄. 값을 저장하기 위해 9바이트가 필요


- DATE : 날짜 및 시간에 대한 기본 유형


- TIMESTAMP : DATE 데이터 유형을 확장하고 연도, 월, 일, 시, 분, 초 및 소수로 표시되는 초 단위를 저장

구문 : TIMESTAMP[(precision)]으로 나타내고 선택적 파라미터인 precision 은 초 필드의 소수부분 자릿수를 지정

   자릿수를 지정하려면 0-9 범위의 정수를 사용해야 함. 기본값은 6


Reference 변수 (참조 변수)

변수가 지정되어야 할 정확한 데이터 형태를 모를 경우 해당 데이터가 들어 있는 컬럼의 정보를 참조하게끔 설정


예 ) Vno emp.empno%TYPE <- emp 테이블의 empno와 동일한 데이터형으로 선언

Vname emp.empno%TYPE <- emp 테이블의 ename 과 동일한 데이터형으로 선언

Vrow emp%ROWTYPE <- emp 테이블의 여러 컬럼을 한꺼번에 저장할 변수로 선언


ROWTYPE 변수는 하나의 테이블에 여러 컬럼의 값을 한꺼번에 저장할 수 있는 변수를 의미


(1) TYPE 변수를 사용하여 데이터 조회

emp3 테이블에서 empno가 7900 번인 사원의 empno, ename, sal 을 조회하여 화면에 출력

-실습을 위해 emp테이블을 복사해서 emp3 테이블을 생성

SCOTT>CREATE TABLE emp3 

2    AS

3    SELECT empno,ename,sal

4    FROM emp ;


SCOTT>SET SERVEROUTPUT ON ;

SCOTT>DECLARE

2    vno emp3.empno%TYPE ;

3    vname emp3.ename%TYPE ;

4    vsal emp3.sal%TYPE ;

5    BEGIN

6    SELECT empno,ename,sal

7    INTO vno,vname,vsal

8    FROM emp3

9    WHERE empno=7900 ; 

10  DBMS_OUTPUT.PUT_LINE(vno||'  '||vname||'   '||vsal) ;

11  END ;

12  /


-> 7900 JAMES 950

(2) ROWTYPE 변수를 사용하여 데이터 출력

SCOTT>DECLARE

2    v_row emp3%ROWTYPE ;

3    BEGIN

4    SELECT * INTO v_row

5    FROM emp3

6    WHERE empno=7900 ;

7    DBMS_OUTPUT.PUT_LINE(v_row_empno||'**'||v_row.ename||'**'||v+row.sal_ ;

8    END ;

9    /


-> 7900**JAMES**950


(3) ROWTYPE 변수를 활용한 데이터의 입력

SCOTT>CREATE TABLE row_test

2    (no NUMBER,

3     name VARCHAR2(10),

4     hdate DATE) ;


SCOTT>CREATE TABLE row_test2

2    AS SELECT * FROM row_test ; 


SCOTT>INSERT INTO row_test VALUES (1,'AAA',SYSDATE) ;


SCOTT>INSERT INTO row_test VALUES (2,'BBB',SYSDATE) ;


SCOTT>INSERT INTO row_test VALUES (3,'CCC',SYSDATE) ;


SCOTT>COMMIT ;


SCOTT>DECLARE

2    v_record row_test%ROWTYPE ;

3    BEGIN

4    SELECT * INTO v_record

5    FROM row_test

6    WHERE no=1 ;

7    INSERT INTO row_test2

8    VALUES v_record ; 

9    END ;

10   /


SCOTT>SELECT * FROM row_test2 ;


NO    NAME    HDATE

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

   1     AAA    27-MAR-12


 

(4) ROWTYPE 변수를 활용한 데이터의 변경

SCOTT>DECLARE

2    v_record row_test%ROWTYPE ;

3    BEGIN

4    SELECT * INTO v_record

5    FROM row_test

6    WHERE no=1 ;

7    UPDATE row_test2

8    SET row=v_record

9    WHERE no=1 ;

10   END;

11    /


SCOTT>SELECT * FROM row_test2 ;


NO    NAME    HDATE

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

   1    DDD     27-MAR-12     <- 원래 'AAA' 에서 'DDD' 로 바뀜



변수 예제 1

%TYPE 변수를 사용하여 emp, dept 테이블을 조인하여 empno=7900인 사람의 정보를 4개의 변수에 넣은 후 empno, ename, deptno, dname을 출력


SCOTT>DELCARE

2    v_empno emp.empno%TYPE ; 

3    v_ename emp.ename%TYPE ; 

4    v_deptno dept.deptno%TYPE ;

5    v_dname dept.dname%TYPE ;

6    BEGIN

7    SELECT e.empno, e.ename, d.deptno, d.dname

8    INTO v_empno, v_ename, v_deptno, v_dname

9    FROM emp e,dept d

10   WHERE e.empno=7900 

11   AND e.deptno=d.deptno ;

12   DBMS_OUTPUT.PUT_LINE(v_empno||'  '||v_ename||'  '||v_deptno||'  '||v_dname) ;

13   END ;

14   /

-> 7900 JAMES 30 SALES


변수 예제 2

사용자로부터 두 개의 숫자를 입력 받아서 합을 구하시오


SCOTT>DECLARE

2    v_no1 NUMBER := &no1 ;

3    v_no2 NUMBER := &no2 ;

4    v_sum NUMBER ;

5    BEGIN

6    v_sum := v_no1 + v_no2 ;

7    DBMS_OUTPUT.PUT_LINE('첫 번째 수:'||v_no1||', 두번째 수 :'||v_no2||', 합은 :'||v_sum||' 입니다') ;

8    END ;

9    /

Enter value for no1 : 20

Enter value for no2 : 40

-> 첫 번째 수 : 20, 두번째 수 : 40, 합은 : 60 입니다



복합 변수 ( 조합 변수)

변수 하나 안에 사용자가 원하는 여러 가지 다른 유형의 데이터를 포함해서 사용자가 원하는 새로운 형태로 만듬


복합변수 - Record Type 변수Table Type (컬렉션 타입) 변수로 나눌 수 있음

Record Type 변수 : 데이터 타입이 다른 여러 건을 저장할 경우

Table Type (컬렉션 타입) 변수 : 동일한 데이터 타입의 데이터를 여러 건 저장하고 싶을 경우 


(1) Record Type 복합 변수

- 크게 %ROWTYPE 을 사용하는 테이블 기반의 Record Type과 사용자가 원하는 컬럼만을 지정해서 만드는 

프로그래머 정의 기본 Record Type 으로 구분

PL/SQL Record 정의와 선언

1. TYPE type_name IS RECORD ( field_declaration[, field_declaration]...) ;

2. Identifier type_name


Record Type 변수의 선언 및 사용 예 )


프로그래머 정의 Record Type 변수 사용 예 1 :

Record type 변수를 활용하여 부서번호가 30 번인 부서의 부서번호와 부서명과 지역명을 Record type 변수에 저장한 후 출력. 단 record type 의 type 명은 dept_record_type 로 지정하겠음.


SCOTT>DECLARE

2    TYPE dept_record_type IS RECORD

3    (deptno dept.deptno%TYPE,

4     dname dept.dname%TYPE,

5     loc       dept.loc%TYPE) ;

6     v_dept dept_record_type ;

7    BEGIN

8    SELECT deptno, dname, loc

9    INTO v_dept

10   FROM dept

11   WHERE deptno = 30 ;

12   DBMS_OUTPUT.PUT_LINE('부서번호  부서명  위치') ;

13   DBMS_OUTPUT.PUT_LINE(v_dept.deptno||'    '||

14                                         v_dept.dname||'    '||

15                                         v_dept.loc) ;

16    END ;

17    /

부서번호    부서명    위치

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

30             SALES    CHICAGO



프로그래머 정의 Record Type 변수 사용 예 2 :

emp2 테이블을 사용하여 사용자로부터 사원 번호를 입력 받은 후 아래와 같이 사원번호, 사원이름, 직급, 생일, 연락처, 급여를 출력, 단 직급이 없는 사원은 직급을 사원으로 표시해서 출력


Enter value for empno : 20000102

사원번호 : 20000102

사원명 : 김설악

직급 : 사원

생일: 22-MAR-83

연락처 : 031)234-5678

급여 : 30000000


SCOTT>DECLARE

2    TYPE e2_rec_type IS RECORD (

3    vempno    emp2.empno%TYPE,

4    vname      emp2.name%TYPE,

5    vposition   emp2.position%TYPE,

6    vbirth        emp2.birthday%TYPE,

7    vtel           emp2.tel%TYPE,

8    vpay         emp2.pay%TYPE) ;

9    v_e2_record    e2_rec_type ;

10   v_empno emp2.empno%TYPE := '&empno' ;

11   BEGIN

12   SELECT empno,name,NVL(position,'사원'),birthday,tel,pay

13   INTO v_e2_record

14   FROM emp2

15   WHERE empno=v_empno ;

16   DBMS_OUTPUT.PUT_LINE('사원번호:'||v_e2_record.vempno) ;

17   DBMS_OUTPUT.PUT_LINE('사  원 명:'||v_e2_record.vname) ;

18   DBMS_OUTPUT.PUT_LINE('직      급:'||v_e2_record.vposition) ;

19   DBMS_OUTPUT.PUT_LINE('생      일:'||v_e2_record.vbirth) ;

20   DBMS_OUTPUT.PUT_LINE('연  락 처:'||v_e2_record.vtel) ;

21   DBMS_OUTPUT.PUT_LINE('급      여:'||v_e2_record.vpay) ;

22   END ;

23    /



(2) Table Type 변수 (컬렉션 타입)

대부분의 경우 1 개의 컬럼만 저장을 하지만 Row Type 을 사용하여 Record Type 과 같이 여러 가지 유형의 데이터 컬럼을 가질 수도 있음. 그러나 권장방법은 아님


컬렉션 타입의 종류

- 연관 배열

- 중첩 테이블

- VARRAY


연관 배열의 특성

- 연관 배열은 변수 선언 당시 채워지지 않으며 키나 값을 포함하지 않으므로 선언에서 연관 배열을 초기화 할  수 없습니다.

- 연관 배열을 채우려면 명시적 실행문이 필요

- 연관 배열의 크기에 제약이 없음. 따라서 새 행이 추가됨에 따라 연관 배열이 증가하도록 행 수가 동적으로 늘어날 수 있다.


컬렉션 타입 정의와 선언

문법 :

1. TYPE type_name IS TABLE OF {column_type|variable%type|table.column%type}[NOT NULL]|table%ROWTYPE[INDEX BY BINARY_INTEGER] ;

2. Identifier type_name


- Table Type 변수 사용 예 1 :

Table Type 변수를 사용하여 사원번호가 7499 인 사원의 이름을 조회해서 해당 변수에 저장 한 후 출력.

SCOTT>DECLARE

2    t_name    VARCHAR2(20) ;

3    TYPE tbl_emp_name IS TABLE OF

4    emp.ename%TYPE

5    INDEX BY BINARY_INTEGER ;

6    v_name tbl_emp_name ;

7    BEGIN

8    SELECT ename INTO t_name

9    FROM emp 

10   WHERE empno=7499 ;

11   v_name(0) := t_name ;

12   DBMS_OUTPUT.PUT_LINE(v_name(0)) ;

13   END ;

14    /


- Table Type 변수 사용 예2 : 커서를 사용해서 생성하는 방법

professor 테이블의 rowtype 을 가지는 prof_table_type 이라는 이름으로 새로운 타입을 생성 한 후 v_prof_row 라는 변수에 할당. 그리고 v_prof_row 변수의 첫 번째 행 (0번 행) 에 데이터를 입력 한 후 화면에 출력


SCOTT>DECLARE

2    TYPE prof_table_type IS TABLE OF professor%rowtype

3    INDEX BY binary_integer ;

4    v_prof_row prof_table_type ;

5    BEGIN

6    v_prof_row(0).profno := 9000 ;

7    v_prof_row(0).name := 'imsy' ;

8    v_prof_row(0).id := 'imsy_id' ;   

9    v_prof_row(0).position := 'imsy' ;

10  v_prof_row(0).pay := '000' ;  

11   v_prof_row(0).hiredate := sysdate ;

12   DBMS_OUTPUT.PUT_LINE(v_prof_row(0).profno||' '||v_prof_row(0).name||' '||v_prof_row(0).id||' '||

13                                       v_prof_row(0).position||' '||v_prof_row(0).pay||' '||v_prof_row(0).hiredate) ; 

14   END ;

15   /

-> 9000 imsy imsy_id imsy 0 01-JUL-13


- Table Type 변수 사용 예 3 : For 반복문을 사용하여 변수에 여러 건의 데이터를 입력하는 방법


SCOTT>DECLARE

2    TYPE e_table_type IS TABLE OF

3    emp.ename%TYPE

4    INDEX BY BINARY_INTEGER ;

5    tab_type e_table_type ;

6    a BINARY_INTEGER := 0 ;

7    BEGIN

8    FOR i IN (SELECT ename FROM emp) LOOP

9        a := a+1 ;

10       tab_type(a) := i.ename ;

11   END LOOP ;

12   FOR J IN 1..a LOOP

13   DBMS_OUTPUT.PUT_LINE(tab_type(j)) ;

14    END LOOP ;

15    END ;

16    /


-> SMITH

     ALLEN

     WARD

    JONES

....


비 PL/SQL 변수

PL/SQL 안에서만 사용되는 것이 아니라 외부에서도 사용될 수 있는 변수

SQL 환경에서도 쓸 수 있고 PL/SQL 에서도 사용 할 수 있음


- 바인드 변수

호스트 환경에서 생성되어 데이터를 저장하므로 호스트 변수라고도 함. VARIABLE 키워드를 사용하여 생성


사용 예 ) 교수번호가 1001 인 교수의 연봉을 계산하여 바인드 변수에 할당 한 후 출력

SCOTT>VARIABLE v_bind NUMBER ;   --SQL 에서 변수를 선언

SCOTT>BEGIN

2    SELECT (pay*12)+NVL(bonus,0) INTO :v_bind

3    FROM professor

4    WHERE profno=1001 ;

5    END ;

6    /


SCOTT>PRINT v_bind ;  --SQL에서 바인드 변수에 담긴 값을 출력


V_BIND

------

  6700


PRINT 문장으로 매번 확인이 번거로울 경우 SET AUTOPRINT ON ;  명령어를 사용하면 자동으로 바인드 변수값을 출력


PL/SQL 과 SQL 에서 사용되는 주요 데이터 타입 정리



반응형

'오라클 > PL/SQL' 카테고리의 다른 글

PL/SQL sub program  (0) 2014.10.16
PL/SQL 예외처리  (0) 2014.10.16
PL/SQL CURSOR  (0) 2014.10.14
PL/SQL 제어문  (0) 2014.10.13
PL/SQL 시작하기  (0) 2014.10.13
반응형

PL/SQL - Procedural Language/SQL 


PL/SQL 의 런타임 구조

PL/SQL 실행 시 실행 원리




PL/SQL 기본 구조

PL/SQL 은 기본적으로 블록(BLOCK) 구조를 가지고 있다.


블록의 기본 구성은 선언부(DECLARE), 실행부(BEGIN), 예외처리부(EXCEPTION)로 구성

그 블록 안에 블록을 포함시킬 수 있는 데 포함된 블록을 Nested Block(중첩 블록) 이라고 부름


블록의 유형에는 크게 Anonymous PL/SQL Block(익명블록)Stored PL/SQL Block(저장된 블록) 이 있다.

익명블록 = 일회성으로 사용할 경우

저장된 블록 = 서버에 파싱해서 자장해 놓고 주기적으로 반복해서 사용할 경우


 DECLARE(선언부)

 모든 변수나 상수를 선언하는 부분

 BEGIN(실행부) 

 제어문, 반복문, 함수정의 등의 로직을 기술함 (실행) 

 EXCEPTION(예외처리부)

 실행 도중 에러 발생시 해결하는 문장들을 기술

예외 처리부는 경우에 따라 생략 가능 / 단 실행부는 반드시 있어야 함


※ PL/SQL은 기본적으로 처리된 문장을 화면에 출력하지 않는다.

그래서 화면에 출력하기 위해서 아래와 같은 사전작업이 필요


SQL>SET SERVEROUTPUT ON ;      


오류 내용을 보고 싶을 경우


SQL>SET ERRORS ;


PL/SQL 기본 실행 예 )

emp 테이블에서 empno 가 7900 번인 사원의 사번과 이름을 화면에 출력하시오


SCOTT>DECLARE

v_ename emp.ename%TYPE ;

BEGIN

SELECT ename into v_ename

FROM emp

WHERE empno=&empno ;

DBMS_OUTPUT.PUT_LINE ('사원명은'||v_ename||'입니다') ;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE(' 해당 사원이 없습니다 ') ;

WHEN TOO_MANY_ROWS THEN

DBMS_OUTPUT.PUT_LINE(' 사원이 두 명 이상입니다 ') ;

END ;

/

Enter value for empno : 7900

-> 사원명은 JAMES 입니다

Enter value for empno : 8000

-> 해당 사원이 없습니다



1 > PL/SQL 문 내에서의 SQL 문장 사용하기

- END 키워드는 트랜잭션의 끝이 아니라 PL/SQL 블록의 끝을 나타냄

- PL/SQL 은 DDL 문을 직접 지원하지 않는다

- PL/SQL 은 GRANT 또는 REVOKE 와 같은 DCL 문을 직접 지원하지 않는다


1. PL/SQL 내에서의 SELECT 문장 사용하기

문법 : 

SELECT select_list

INTO {variable_name[, variable_name]...| record_name}

FROM table

[WHERE condition] ;


사용 예 1) Professor 테이블에서 교수번호가 1001 번인 교수의 교수번호와 급여를 조회 한 후 변수에 저장해서 출력

SCOTT> DECLARE

2    v_profno professor.profno%TYPE ;

3    v_pay     professor.pay%TYPE ;

4    BEGIN

5    SELECT profno, pay, INTO v_profno, v_pay

6    FROM professor

7    WHERE profno=1001 ;

8    DBMS_OUTPUT.PUT_LINE (v_profno||' 번 교수의 급여는 '||v_pay||' 입니다') ;

9    END ;

10    /

-> 1001 번 교수의 급여는 550 입니다


사용 예 2)emp2 테이블을 사용하여 사원번호를 입력 받아서 사원의 사번과 이름, 생일을 출력하세요.

SCOTT> DECLARE

2    v_empno emp2.empno%TYPE ;

3    v_name emp2.name%TYPE ;

4    v_birth emp2.birthday%TYPE ;

5    BEGIN

6    SELECT empno,name,birthday INTO v_empno,v_name,v_birth

7    FROM emp2

8    WHERE empno=&empno;

9    DBMS_OUTPUT.PUT_LINE (v_empno||' '||v_name||' '||v_birth) ;

10   END ;

11    /

ENTER value for empnno : 20000102

-> 20000102 김설악 22-MAR-83


사용자에게 값을 입력 받아서 변수에 할당 할 때 사용하는 기호 = &(엠퍼센트)


2 > PL/SQL 내에서의 DML 문장 사용하기

INSERT , UPDATE, DELETE, MERGE 문장을 이용하여 PL/SQL 블록 내에서 데이터를 변경 할 수 있다.


(1) INSERT 문장 수행하기 예 1 :

- 이 작업을 하기 위해 테스트용 테이블 pl_test 와 시퀀스를 아래와 같이 먼저 생성

SCOTT>CREATE TABLE pl_test

2    (no number,

3     name varchar2(10)) ;


SCOTT>CREATE SEQUENCE pl_seq ;


- PL/SQL 에서 INSERT 를 수행

SCOTT>BEGIN 

2    INSERT INTO pl_test

3    VALUES(pl_seq.NEXTVAL,'AAA') ;

4    END ;   

5    /

PL/SQL procedure successfully completed.


SCOTT>/

PL/SQL procedure successfully completed.


SCOTT>SELECT * FROM pl_test ;


NO   NAME 

---  -----

   1    AAA

   2    AAA


SCOTT>commit ;

Commit complete


(2) INSERT 문장 수행하기 예 2 :

- 작업을 수행하기 전에 pl_test2 테이블 생성

SCOTT>CREATE TABLE pl_Test2

2    (no number,

3     name varchar2(10),

4     addr varchar2(10) ) ;


사용자로부터 번호(no) , 이름(name), 주소(addr) 값을 입력 받은 후 pl_test2 테이블에 입력하는 PL/SQL 문장을 작성

SCOTT>SET VERIFY OFF

SCOTT>DECLARE

2    v_no number :='&no' ;

3    v_name varchar2(10) := '&name' ;

4    v_addr varchar2(10) := '&addr' ;

5    BEGIN

6    INSERT INTO pl_test2 VALUES(v_no, v_name, v_addr) ;

7    END ;

8    /

Enter value for no : 10

Enter value for name : AAA

Enter value for addr : 서울


SCOTT>SELECT * FROM pl_test2 ;


NO    NAME    ADDR

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

  10    AAA       서울



(3) PL/SQL 에서 UPDATE 수행

SCOTT>BEGIN

2    UPDATE pl_test

3    SET name='BBB'

4    WHERE no = 2 ;

5    END ;

6    /


SCOTT>SELECT * FROM pl_test ;


NO    NAME

---   -----

   1    AAA   

   2    BBB

SCOTT>commit ;


(4) PL/SQL 에서 DELETE 수행

SCOTT>BEGIN

2    DELETE FROM pl_test

3    WHERE no=1 ;

4    END ;

5    /


SCOTT>SELECT * FROM pl_test ;


NO    NAME

---   -----

   2    BBB

SCOTT>commit ;


(5) PL/SQL 에서 MERGE 작업 수행

- 작업을 수행하기 위해 연습용 테이블 pl_merge1 과 pl_merge2 를 생성


SCOTT>CREATE TABLE pl_merge1

2    (no number,

3     name varchar2(10) ) ;


SCOTT>CREATE TABLE pl_merge2

2    AS SELECT * FROM pl_merge1 ;


SCOTT>INSERT INTO pl_merge1 VALUES(1,'AAA') ;


SCOTT>INSERT INTO pl_merge1 VALUES(2,'BBB') ;


SCOTT>INSERT INTO pl_merge2 VALUES(1,'CCC') ;


SCOTT>INSERT INTO pl_merge2 VALUES(3,'DDD') ;


SCOTT>commit ;


SCOTT>SELECT * FROM pl_merge1 ;


NO    NAME

---   -----

   1     AAA

   2     BBB


SCOTT>SELECT * FROM pl_merge2 ;


NO    NAME

---   -----

   1     CCC

   3     DDD


SCOTT> BEGIN

2    MERGE INTO pl_merge2 m2

3    USING pl_merge1 m1

4    ON(m1.no = m2.no)

5    WHEN MATCHED THEN

6    UPDATE SET

7    m2.name = m1.name

8    WHEN NOT MATCHED THEN

9    INSERT VALUES(m1.no , m1.name) ;

10   END ;

11    /


SCOTT>SELECT * FROM pl_merge1 ;


NO    NAME

---   -----

   1     AAA

   3     DDD

   2     BBB     <- 이줄 추가되어 있음


PL/SQL 에서의 렉시칼 (Lexical)

렉시칼 이란 PL/SQL 안에 사용되는 문자들을 의미하며 식별자, 구분자, 리터럴, 주석등으로 구성


식별자 - PL/SQL 객체에게 부여되는 이름 (테이블 이름이나 변수명 등)

아래와 같은 경우 식별자를 쌍따옴표로 묶어서 사용할 수 있다

- 식별자의 대소문자 구분이 필요한 경우

- 공백과 같은 문자를 포함할 경우

- 예약어를 사용해야 할 경우


구분자 - 특별한 의미를 지닌 기호, 예를 들어 SQL 문장을 끝낼 때는 끝내는 의미를 가진 ; 을 사용



리터럴 - 변수에 할당되는 모든 값, 식별자가 아닌 모든 문자, 숫자, 부울 또는 날짜 값

- 문자 리터럴 : 모든 문자열 리터럴은 데이터 유형이CHAR 또는 VARCHAR2 이므로 문자 리터럴이라고 함

- 숫자 리터럴 : 정수 또는 실수 값을 나타냄

- 부울 리터럴 : 부울 변수에 할당된 값, TRUE, FALSE 및 NULL 은 부울 리터럴이거나 키워드

- 주석 : 코드의 설명이나 해설등을 기록해 두는 것


PL/SQL 에서의 사용되는 주요 연산자들



PL/SQL 에서 블록 구문 작성시 주의사항

1) 문자 리터럴이나 날짜 리터럴 사용시 반드시 홀 따옴표로 묶어서 표시

2) 문장에서의 주석은 한 줄일 경우 --(하이픈 두개) 를 써서 표시하고 여러 줄 일 경우 /* */ 기호를 사용해서 표시

3) 프로시져 내에서는 단일행 함수만을 사용해야 하며 DECODE 함수나 그룹함수는 사용할 수 없음

4) 데이터의 형 변환에 주의


반응형

'오라클 > PL/SQL' 카테고리의 다른 글

PL/SQL sub program  (0) 2014.10.16
PL/SQL 예외처리  (0) 2014.10.16
PL/SQL CURSOR  (0) 2014.10.14
PL/SQL 제어문  (0) 2014.10.13
PL/SQL 변수  (0) 2014.10.13
반응형

Sub Query 문법 :

SELECT select_list

FROM Table 또는 View

WHERE 조건 연산자 ( SELECT select_list

FROM Table

WHERE 조건) ;


위 문법에서 괄호 안에 있는 쿼리를 Sub Query 라고 부르고 괄호 밖에 있는 쿼리를 Main Query 라고 부른다


Sub Query 의 종류

1) 단일 행 Sub Query

서브 쿼리의 결과가 1 개의 행만 나오는 것 


WHERE 절에서 사용되는 연산자

연산자 

의미 

같다 

<> 

같지 않다 

크다 

<=

크거나 같다 

작다 

<= 

작거나 같다 


(1) 단일 행 Sub Query 연습 문제 1 : 

Student 테이블과 department 테이블을 사용하여 이윤나 학생과 1 전공이 동일한 학생들의 이름과 1전공 이름을 출력

SCOTT> SELECT s.name , d.dname

FROM studnet s , department d

WHERE s.deptno1 = d.deptno

AND deptno1 = ( SELECT deptno1

FROM student

WHERE name = '이윤나') ;


(2) 단일 행 Sub Query 연습 문제 2 :

Professor 테이블과 department 테이블을 조회하여 입사일이 송도권 교수보다 나중에 입사한 사람의 이름과 입사일, 학과명을 출력

SCOTT> SELECT p.name , p.hiredate, d.dname

FROM professor p , department d

WHERE p.deptno = d.deptno

AND hiredate > ( SELECT hiredate

FROM professor

WHERE name = '송도권' ) ;


(3) 단일 행 Sub Query 연습 문제 3 :

Student 테이블에서 1 전공이 101번인 학과의 평균 몸무게보다 몸무게가 많은 학생들의 이름과 몸무게를 출력

SCOTT> SELECT name , weight

FROM student

WHERE weight > (SELECT avg(weight)

FROM student

WHERE deptno1 = 101) ;


(4) 단일 행 Sub Query 연습 문제 3 :

Professor 테이블에서 심슨 교수와 같은 입사일에 입사한 교수 중에서 조인형 교수보다 월급을 적게 받는 교수의 이름과 급여, 입사일을 출력

SCOTT> SELECT name , hiredate

FROM professor

WHERE hiredate = (SELECT hiredate

    FROM professor

    WHERE name = '심슨' )

WHERE pay < (SELECT pay

   FROM professor

   WHERE name = '조인형' ) ;


2) 다중 행 Sub Query

서브 쿼리의 결과가 2건 이상 출력되는 것

(1) 다중 행 Sub Query 예 1 :

emp2 테이블과 dept2 테이블을 참조하여 근무지역이 서울 지사인 모든 사원들의 사번과 이름, 부서번호를 출력

SCOTT> SELECT empno, name, deptno

FROM emp2

WHERE deptno IN (SELECT dcode

    FROM dept2

    WHERE area = '서울지사' ) ;


위 서브 쿼리의 결과가 1000,1001,1002,1010 4건의 결과가 나옴. 그래서 다중행 서브쿼리 사용


(2) 다중 행 Sub Query 예 2 - Exists 연산자 사용

Sub Query 의 내용을 먼저 수행해서 그 결과가 1건이라도 나오면 메인쿼리를 수행하고 결과가 한 건도 나오지 않으면 메인쿼리를 아예 실행하지 않는다.


Exists 연산자와 IN 연산자의 차이점


위 결과를 보면 EXISTS 연산자는 서브쿼리의 결과가 있으면 그 결과와 관계없이 메인쿼리를 수행하는 연산자

IN 연산자는 서브쿼리의 결과가 있으면 그 결과에 해당되는 메인쿼리를 수행


(3) 다중 행 Sub Query 연습문제 1 :

emp2 테이블을 사용하여 전체 직원 중 과장 직급의 최소 연봉자보다 연봉이 높은 사람의 이름과 직급, 연봉을 출력

SCOTT> SELECT name , position , to_char(pay,'999,999,999') 

FROM emp2

WHERE pay > any ( SELECT pay

FROM emp2

WHERE position = '과장' ) ;


(4) 다중 행 Sub Query 연습문제 2 :

student 테이블을 조회하여 전체 학생 중에서 체중이 4학년 학생들의 체중에서 가장 적게 나가는 학생보다 몸무게가 적은 학생의 이름과 학년과 몸무게를 출력

SCOTT> SELECT name , grade , weight

FROM student

WHERE weight < all ( SELECT avg(weight)

FROM student

WHERE grade = 4 ) ;


(5) 다중 행 Sub Query 연습문제 3 :

emp2 테이블과 dept2 테이블을 조회하여 각 부서별 평균 연봉을 구하고 그 중에서 평균 연봉이 가장 적은 부서의 평균 연봉보다 적게 받는 직원들의 부서명, 직원명, 연봉을 출력

SCOTT> SELECT d.dname , e.name , to_char(e.pay,'999,999,999')

FROM dept2 d , emp2 e

WHERE d.dcode = e.deptno

AND pay < all ( SELECT avg(pay)

FROM emp2

GROUP BY deptno)

ORDER BY 3 ;

3) 다중 컬럼 SUB Query 

서브 쿼리의 결과가 여러 컬럼인 경우를 말합니다.


(1) 다중 컬럼 Sub Query 예 1 :

student 테이블을 조회하여 각 학년별로 최대키를 가진 학생들의 학년과 이름과 키를 출력

(2) 다중 컬럼 Sub Query 연습문제 1 :

professor 테이블과 department 테이블을 조회하여 각 학과별로 입사일이 가장 오래된 교수의 교수번호와 이름, 학과명을 출력 ( 입사일 순으로 오름차순 정렬)

SCOTT> SELECT p.profno , p.name , p.hiredate, d.dname

FROM professor p , department d

WHERE p.deptno = d.deptno

AND (p.profno,p.hiredate) IN ( SELECT profno , MIN(hiredate)

FROM professor

GROUP BY deptno)

ORDER BY 3 ;


(3) 다중 컬럼 Sub Query 연습문제 2 :

emp2 테이블을 조회하여 직급별로 해당 직급에서 최대 연봉을 받는 직원의 이름과 직급, 연봉을 출력. 연봉순으로 오름차순 정렬

SCOTT> SELECT name, position, pay

FROM emp2

WHERE (position,pay) IN (SELECT position,MAX(pay)

FROM emp2

GROUP BY position)

ORDER BY 3 ;



4) 상호 연관 Sub Query

메인 쿼리 값을 서브 쿼리에 주고 서브쿼리를 수행 한 후 그결과를 다시 메인 쿼리로 반환해서 수행하는 서브쿼리

(1) 상호연관 Sub Query 예 1:

emp2 테이블을 조회해서 직원 들 중에서 자신의 직급의 평균연봉과 같거나 많이 받는 사람들의 이름과 직급, 현재 연봉을 출력



반응형
반응형

DML (Data Manipulation Language) : INSERT (입력) , UPDATE (변경) , DELETE (삭제) , MERGE(병합)


1. INSERT

테이블에 새로운 데이터를 입력할 때 사용, 데이터 입력시 숫자 값 이외에는 데이터를 '(홀따옴표)로 감싸야 함


1) INSERT 를 사용하여 단일 행 입력

문법 :

INSERT INTO table(column1, column2, ....)

VALUES (value 1, value 2, ....) ;


사용 예 1. dept2 테이블에 아래와 같은 내용으로 새로운 부서정보 입력

* 부서번호 : 9000

* 부서명 : 특판1팀

* 상위부서 : 영업부

* 지역 : 임시지역

SCOTT>INSERT INTO dept2 (dcode, dname, pdept, area)

2    VALUES (9000, '특판1팀', '영업부', '임시지역') ;


※ 모든 컬럼에 데이터를 넣을 경우에는 테이블 이름 뒤 컬럼이름을 생략 가능

SCOTT>INSERT INTO dept2

2    VALUES (9001, '특판2팀', '영업부', '임시지역') ;


사용 예2. 날짜 데이터 입력

* 교수번호 : 5001 

* 교수이름 : 박동주

* ID : Love_me

* POSITION : 정교수

* PAY : 510

* 입사일  2014년 5월 14일

SCOTT>INSERT INTO professor (profno, name, id, position, pay, hiredate)

2    VALUES (5001, '박동주', 'Love_me', '정교수', 510, '2014-05-14')

-> 위와 같이 입력할 경우 날짜 형태가 맞지않아 에러가 날 것이다

리눅스용 날짜 방식은 (dd-mon-yy) 이고 윈도우용 날짜 방식은 (yyyy-mm-dd)이기 때문에

미리 날짜형식을 yyyy-mm-dd 로 바꾸고 입력

SQL>ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD:HH24:MI:SS' ;


사용 예3. Null 값 입력

* 자동 NULL 값 입력하기

데이터를 입력할 때 컬럼에 값을 안 주면 자동으로 NULL 값이 들어감


* 수동 NULL 값 입력하기

데이터부분에 NULL 값을 적어주면 됨


2) INSERT 를 사용하여 여러 행 입력

SCOTT>INSERT INTO professor2

2    SELECT * FROM professor ;

-> professor 테이블에 있는 데이터를 professor2 테이블로 입력, 

위와 같이 입력할 때 professor2 테이블과 professor 테이블의 컬럼의 개수와 데이터 형이 동일해야 한다.


3) INSERT ALL 을 이용한 여러 테이블에 여러 행 입력


사용 예 1.) 다른 테이블에 한꺼번에 데이터 입력하기

SCOTT>INSERT ALL

2    INTO p_01 (no , name)

3    VALUES (1, 'AAA')

4    INTO p_02 (no , name)

5    VALUES (2, 'BBB')

6    SELECT * FROM dual ;


사용 예2.) 다른 테이블의 데이터를 가져와서 입력하기

professor 테이블에서 교수번호가 1000 번에서 1999 번까지 인 교수의 번호와 교수이름은 p_01 테이블에 입력

교수번호가 2000 번에서 2999 번까지 인 교수의 번호와 이름은 p_02 테이블에 입력

SCOTT>INSERT ALL

2    WHEN profno BETWEEN 1000 AND 1999 THEN

3    INTO p_01 VALUES(profno, name)

4    WHEN profno BETWEEN 2000 AND 2999 THEN

5    INTO p_02 VALUES(profno, name)

6    SELECT profno, name

7    FROM professor ;


사용 예3.) 다른 테이블에 동시에 같은 데이터 입력하기

professor 테이블에서 교수번호가 3000 번에서 3999 번인 교수들의 교수 번호와 이름을 p_01 테이블과 p_02 테이블에 동시에 입력

SCOTT>INSERT ALL

2    INTO p_01 VALUES (profno, name)

3    INTO p_02 VALUES (profno, name)

4    SELECT profno, name

5    FROM professor

6    WHERE profno BETWEEN 3000 AND 3999 ;


2. UPDATE

기존 데이터를 다른 데이터로 변경할때 사용


문법 :

UPDATE table

SET column = value

WHERE 조건 ;


사용 예 1.

professor 테이블에서 직급이 조교수 인 교수들의 BONUS 를 100 만원으로 인상하세요

SCOTT>UPDATE professor

2    SET bonus = 100

3    WHERE position = '조교수' ;


사용 예 2.

professor 테이블에서 차범철 교수의 직급과 동일한 직급을 가진 교수들 중 현재 급여가 250만원이 안 되는 교수들의 급여를 15% 인상하세요.

SCOTT>UPDATE professor

2    SET pay = pay * 1.15

3    WHERE position = (SELECT position   

4                               FROM professor

5                               WHERE name = '차범철' )

6    AND pay < 250 ;


3. DELETE

데이터를 삭제하는 구문

문법 :

DELETE FROM table

WHERE 조건 ;


사용 예 1.

dept2 테이블에서 부서번호(DCODE)가 9000 번에서 9100 번 사이인 매장들을 삭제

SCOTT>DELETE FROM dept2

2    WHERE dcode BETWEEN 9000 AND 9100 ;



4. MERGE

여러 테이블의 데이터를 합치는 병합을 의미

문법 :

1 MERGE INTO Table1

2   USING Table2

3   ON (병합 조건절)

4   WHEN MATCHED THEN

5     UPDATE SET 업데이트 내용

6     DELETE WHERE 조건

7   WHEN NOT MATCHED THEN

8     INSERT VALUES (컬럼이름) ;

문법 설명 :

Table1 과 Table2 의 내용을 합쳐서 Table1 에 모으는 것.

이때 기준은 3행의 조건, 3행의 조건이 만족한다면(4행) 기존 Table1 에 있던 해당 내용은 Table2 의 내용으로 UPDATE 또는 DELETE 가 수행되며 조건이 만족하지 않은다면 (7행) Table2 의 내용이 Table1에 신규로 INSERT 된다.


MERGE 작업을 조금이라도 빨리 수행하기 위해서는 위 문법에서 3행의 조건절에 인덱스가 잘 만들어져 있어야 한다.



5. TRANSACTION 관리

논리적인 작업 단위, 여러가지 DML 작업들을 하나의 단위로 묶어 둔 것을 의미

트랜잭션의 시작은 DML 이고, 완료하려면 TCL, DCL, DDL이 입력되면 된다.


COMMIT - 트랜잭션 내의 작업의 결과를 확정하는 명령어

ROLLBACK - 트랜잭션 내의 모든 명령어들을 취소하는 명령어


DML 작업을 한 후에는 반드시 COMMIT 이나 ROLLBACK 명령을 수행해야 작업이 마무리 된다.


반응형

'오라클 > SQL' 카테고리의 다른 글

sql 쿼리결과를 파일로 저장  (0) 2015.07.03
DDL  (0) 2014.10.12
JOIN 함수  (0) 2014.10.10
그룹함수 (연습문제)  (1) 2014.10.08
복수행 함수 (그룹 함수)  (1) 2014.10.08
sql 단일행 함수 - 정규식  (2) 2014.10.01
sql 단일행 함수 - 일반 함수  (0) 2014.09.30
반응형

DDL (Data Definition Language) - CREAT (생성) , ALTER (수정) , TRUNCATE (잘라내기) , DROP (삭제)


1.CREATE


※ 테이블 생성시 제한 사항

1. 테이블 이름은 반드시 문자로 시작해야 한다. 숫자로 시작은 불가능하고 포함되는것은 가능


2. 테이블 이름이라 컬럼 이름은 최대 30 bytes 까지 가능, 한글로 테이블 이름을 생성할 경우 최대 15글자까지


3. 테이블 이름은 한 명의 사용자가 다른 오브젝트들의 이름과 중복으로 사용할 수 없다.

ex) scott 사용자가 테이블명을 test로 생성한 후 인덱스 이름을 test로 동일하게 사용하는게 불가능

scott 사용자가 test 테이블을 생성하고 다른 사용자인 hr 사용자도 test 테이블을 사용가능

4. 테이블 이름이나 오브젝트 이름을 오라클이 사용하는 키워드를 사용하지 않기를 권장

오라클 키워드라 함은 오라클에서 사용하는 미리 정해진 SELECT , FROM 들과 같은 단어를 말함


1) 일반 테이블 생성하기

SCOTT>CREATE TABLE ddl_test

2    ( no       NUMBER(3) ,

3      name   VARCHAR(10) ,

4      birth     DATE               DEFAULT SYSDATE ) ;

 

ddl_test 명의 테이블생성, no라는 컬럼은 숫자 데이터만 들어갈 수 있으며 최대길이는 3자리

name 컬럼은 가변형 문자가 들어갈 수 있으며 최대길이는 10bytes

birth 컬럼은 날짜 데이터만 들어갈 수 있으며 아무 값도 안들어올 경우 기본값 으로 현재 날짜 자동입력


2) 기본 입력값을 설정하면서 생성하기 

SCOTT>CREATE TABLE ddl_test2

2    ( no           NUMBER(3,1)     DEFAULT 0 ,

3      name       VARCHAR2(10)   DEFAULT 'NO' ,

4      hiredate    DATE                DEFAULT SYSDATE ) ;  


1) 에서 생성한 테이블은 사용자가 값을 입력하지 않을 경우 기본적으로 NULL값이 자동입력된다.

그러나 DEFAULT 적고 뒤에 값을 적어놓으면 사용자가 값을 입력하지 않을 경우 DEFAULT 뒤에 적힌 값을 자동으로 넣으라는 의미



3) Global Temporary Table (임시 테이블) 생성하기

데이터베이스에 저장할 목적이 아닌 임시 작업용 데이터를 저장하기 위해 만들어짐

트랜잭션이 끝나거나 세션이 종료되면 테이블의 데이터는 사라짐


문법 : 

CREATE GLOBAL TEMPORARY TABLE 테이블명

( 컬럼1 데이터타입 ,

   컬럼2 데이터타입 ,

   ON COMMIT [delete|preserve]ROWS ;

위 문법에서 ON COMMIT delete ROWS 를 사용하면 COMMIT 시 데이터를 삭제

ON COMMIT preserve ROWS 를 사용하면 세션이 종료되야 데이터가 사라짐

기본값은 ON COMMIT delete ROWS


특징 :

1. Redo Log 를 생성하지 않습니다.

2. Index , View , Trigger 를 생성할 수 있으나 이 오브젝트 들의 타입도 전부 Temporary 입니다.

3. 이 테이블에 들어 있는 데이터는 이전이나 백업을 할 수 없습니다.


4) 테이블 복사하기 (CTAS)

새로운 테이블을 생성 할 때 기존에 만들어져 있던 테이블을 복사


1) 모든 컬럼 다 복사하기

SCOTT>CREATE TABLE dept3

2    AS

3    SELECT * FROM dept2 ;

-> dept2 테이블과 똑같은 컬럼과 데이터를 가진 dept3 테이블 생성


2) 특정 컬럼만 복사하기

SCOTT>CREATE TABLE dept4

2    AS

3    SELECT dcode, dname

4    FROM dept2 ;

-> dept2 테이블의 dcode, dname 컬럼만 복사해서 dept4 테이블 생성


3) 테이블의 구조(컬럼) 만 복사하고 데이터는 안 가져오기

SCOTT>CREATE TABLE dept5

2    AS

3    SELECT * FROM dept2

4    WHERE 1=2 ;       (틀린 조건만 적어주면 됨)

-> dept2 테이블의 데이터는 제외하고 컬럼만 복사해서 dept5 테이블 생성


5) 가상컬럼 테이블 생성하기 (11g 부터 추가됨)

step1. 가상 컬럼을 가지는 vt001 테이블 생성

- SCOTT>CREATE TABLE vt001

2    ( no1 number ,

3      no2 number , 

4      no3 number GENERATED ALWAYS AS (no1 + no2) VIRTUAL ) ;

-> no3 = no1 + no2 값을 가지는 가상컬럼


step2. vt001 테이블에 데이터 입력

- SCOTT>INSERT INTO vt001 VALUES (1,2,3) ;        -> no3 은 가상컬럼이기에 값을 INSERT 할수 없다.


- SCOTT>INSERT INTO vt001(no1,no2) 

2       VALUES (1,2) ;

-> no1 컬럼에 1 을 넣고 no2 컬럼에 2 를 넣으면 가상컬럼 no3 은 자동으로 no1 + no2 값이 입력된다.



2. ALTER

만들어져 있는 오브젝트를 변경하는 명령어

테이블 같은 경우 컬럼을 추가하거나 삭제하거나, 컬럼 이름이나 테이블 이름을 바꾸는 등의 작업


※ ALTER 명령어 사용시 사용량이 많을 때, 절대 사용하면 안됨. 디비가 죽을 수 도 있음

1) 새로운 컬럼 추가하기 

SCOTT>ALTER TABLE dept6

2    ADD (LOC VARCHAR2(10) ;

-> dept6 테이블에 LOC라는 컬럼을 추가


2) 테이블의 컬럼 이름 변경하기

SCOTT>ALTER TABLE dept6 RENAME COLUMN LOC TO AREA ;

-> dept6 테이블의 LOC 컬럼명을 AREA 로 변경


테이블명 변경은 그냥 RENAME 명령어로 변경하면됨

SCOTT>RENAME dept6 TO dept7 ;

-> dept6 테이블명을 dept7 로 변경


3) 컬럼의 데이터 크기를 변경하기

SCOTT>ALTER TABLE dept7

2    MODIFY(dcoe, VARCHAR2(10)) ;

-> 기존에 dcode 데이터 크기 6bytes 에서 10bytes 로 변경


4) 컬럼 삭제하기

SCOTT>ALTER TABLE dept7 DROP COLUMN loc ;

-> dept7 테이블의 loc 라는 컬럼 삭제


만약 참조키로 설정되어 있는 부모 테이블의 컬럼을 삭제하려 할 경우 에러가 발생하는데 이땐 아래와 같은 방법사용

SCOTT>ALTER TABLE dept7 DROP COLUMN loc CASCADE CONSTRAINTS ;


5) 읽기 전용 테이블로 변경 -11g 에서 생김

테이블의 내용을 모두 변경은 할 수 없게 하고 조회만 가능하게 설정

SCOTT>ALTER TABLE t_read read only ;

-> t_read 테이블을 읽기 전용으로 변경  (read only 부분을 read write 로 바꾸면 읽고 쓰기 가능)



3. TRUNCATE 명령

테이블의 데이터를 전부 삭제하고 사용하고 있던 공간을 반납하는 명령어, 테이블 자체가 삭제되지는 않음

또한 테이블에 생성되어 있던 인덱스의 내용도 함께 Truncate 됨


SCOTT>TRUNCATE TABLE dept7 ;


4. DROP 명령

테이블 자체를 삭제하는 명령어


SCOTT>DROP TABLE dept7 ;


5. DELETE , TRUNCATE, DROP 명령어의 차이점

DELETE - 데이터는만 지워지고 디스크 상의 공간은 그대로 남아있음

TRUNCATE - 최초에 테이블이 만들어졌던 상태, 데이터가 하나도 없는 상태로 모든 데이터를 삭제하고 컬럼값만 남김

DROPt - 데이터와 테이블 전체를 삭제


6. 데이터 딕셔너리 (Dictionary)

오라클 데이터베이스를 운영하기 위한 정보들을 모두 특정한 곳에 모아두고 관리하는 것


딕셔너리에 저장되는 정보

- 오라클 데이터베이스의 메모리 구조와 파일에 대한 구조 정보들

- 각 오브젝트들이 사용하고 있는 공간들의 정보들

- 제약 조건 정보들

- 사용자에 대한 정보들

- 권한이나 프로파일 , 롤에 대한 정보들

- 감사(Audit) 에 대한 정보들


- 이러한 정보들은 중요한 정보이기에 오라클은 이 딕셔너리를  Base table 과 Data Dictionary View 로 나누어 두고, 

base table 은 DBA라 할 지 라도 접근을 못하게 막아놓음.

- 사용자(DBA포함)들은 Data Dictionary View 를 통해서만 딕셔너리를 select 할 수 있게 허락함

- base table 은 database를 생성하는 시점에 자동으로 만들어짐

- data dictionary view 는 catalog.sql 이란 파일이 수행되어야 만들어짐

- catalog.sql 이란 파일은 DBCA로 database를 생성 할 때는 자동으로 수행되지만 create database 라는 명령어로 수동으로 database를 생성할 때는 수행되지 않으므로 DBA가 수동으로 생성해야함


Data Dictionary View 의 종류

1. Static Data Dictionary View

- 접두어가 DBA_ , ALL_ ,USER_ 로 시작되는 3가지

USER_ = 해당 사용자가 생성한 오브젝트들만 조회 할 수 있다

ALL_ = 해당 사용자가 생성한 오브젝트를 포함하여 해당 사용자가 접근 가능한 모든 오브젝트를 조회 할 수 있다

DBA_ = 데이터베이스 내의 거의 모든 오브젝트들을 다 볼수 있지만 DBA권한을 가진 사람만이 이 딕셔너리를 조회             할 수 있다


2. Dynamic Performance View

- 접두어가 V$ 로 시작하는 것




반응형

'오라클 > SQL' 카테고리의 다른 글

sql 쿼리결과를 파일로 저장  (0) 2015.07.03
DML  (0) 2014.10.12
JOIN 함수  (0) 2014.10.10
그룹함수 (연습문제)  (1) 2014.10.08
복수행 함수 (그룹 함수)  (1) 2014.10.08
sql 단일행 함수 - 정규식  (2) 2014.10.01
sql 단일행 함수 - 일반 함수  (0) 2014.09.30
반응형

JOIN 함수

여러 곳의 테이블에 흩어져 있는 정보중 사용자가 필요한 정보만 가져와서 가상의 테이블처럼 만들어서 결과를 볼 수 있게끔 하는 방법


INNER JOIN (이너조인) - 테이블에 데이터가 존재하는 경우에만 값을 출력

OUTER JOIN (아우터조인) - 한쪽 테이블에는 데이터가 있고 다른 한쪽에는 데이터가 없을 경우 데이터가 있는 쪽 테이블의                                          내용을 전부 출력하게 하는 방법


Oracle 제품에서만 사용되는 Oracle 용 Join 과 모든 제품들에서 공통적으로 사용 가능한 ANSI Join 방법 두가지가 있다.


- Oracle Join 구문 :

SQL> SELECT e.ename , d.dname

      2  FROM EMP e , dept d ;


- ANSI Join 구문 :

SQL> SELECT e.ename , d.dname

     2  FROM emp e CROSS JOIN dept d




1. EQUI Join (등가 Join)

양쪽 테이블에 같은 조건이 존재할 경우의 값만을 가져오는 Join


- Oracle Join 구문 :

SCOTT>SELECT s.name "학생이름" , s.deptno1 "학과번호", d.dname "학과이름"

2    FROM student s , department d

3    WHERE s.deptno1 = d.deptno ;


- ANSI Join 구문 :

SCOTT>SELECT s.name "학생이름" , s.deptno1 "학과번호", d.dname "학과이름"

2    FROM student s JOIN department d

3    ON s.deptno1 = d.deptno ;


- Oracle Join 구문 :

SCOTT>SELECT s.name "학생이름" , d.dname "학과이름" , p.name "교수이름"

2    FROM student s , department d , professor p

3    WHERE s.deptno1 = d.deptno

4    AND s.profno = p.profno ;


- ANSI Join 구문 :

SCOTT>SELECT s.name "학생이름" , d.dname "학과이름" , p.name "교수이름"

2    FROM student s JOIN department d

3    ON s.deptno1 = d.deptno

4    JOIN professor p

5    ON s.profno = p.profno ;



- Oracle Join 구문 :

SCOTT>SELECT s.name "학생이름" , p.name "지도교수명"

2    FROM student s , professor p

3    WHERE s.profno = p.profno

4    AND s.deptno1 = 101 ;


- ANSI Join 구문 :

SCOTT>SELECT s.name "학생이름" , p.name "지도교수명"

2    FROM student s JOIN professor p

3    ON s.profno = p.profno

4    AND s.deptno1 = 101 ;



2. NON-Equit Join (비 등가 Join)

양쪽 테이블에 있는 데이터가 서로 같은 조건이 아닌 크거나 작어나 하는 경우의 JOIN


- Oracle Join 구문 :

SCOTT>SELECT go.gname "고객명" , go.point "POINT" , gi,gname "상품명"

2    FROM gogak go , gift gi

3    WHERE go.point BETWEEN gi.g_start AND gi.g_end ;


- ANSI Join 구문 :

SCOTT>SELECT go.gname "고객명" , go.point "POINT" , gi,gname "상품명"

2    FROM gogak go JOIN gift gi

3    ON go.point BETWEEN gi.g_start AND gi.g_end ;


- Oracle Join 구문 :

SCOTT>SELECT gI.gname "상품명" , COUNT(*) "필요수량"

2    FROM gogak go , gift gi

3    WHERE go.point BETWEEN gi.g_start AND gi.g_end ;

4    GROUP BY gi.gname ;


- ANSI Join 구문 :

SCOTT>SELECT gI.gname "상품명" , COUNT(*) "필요수량"

2    FROM gogak go JOIN gift gi

3    ON go.point BETWEEN gi.g_start AND gi.g_end ;

4    GROUP BY gi.gname ;


- Oracle Join 구문 :

SCOTT>SELECT go.gname "고객명" , go.point "POINT" , gi.gname "상품명"

2    FROM gogak go , gift gi

3    WHERE gi.g_start <= go.point

4    AND gi.gname = '산악용자전거' ;


- ANSI Join 구문 :

SCOTT>SELECT go.gname "고객명" , go.point "POINT" , gi.gname "상품명"

2    FROM gogak go JOIN gift gi

3    ON gi.g_start <= go.point

4    AND gi.gname = '산악용자전거' ;


- Oracle Join 구문 :

SCOTT>SELECT e.name "이름" , trunc((sysdate-e.birthday)/365,0) "현재나이" , e.position "현재직급", 

g.position "예상직급"

2    FROM emp2 e , p_grade g

3    WHERE trunc((sysdate-e.birthday)/365,0) BETWEEN g.s_age AND g.e_age ;


- ANSI Join 구문 :

SCOTT>SELECT e.name "이름" , trunc((sysdate-e.birthday)/365,0) "현재나이" , e.position "현재직급", 

g.position "예상직급"

2    FROM emp2 e JOIN p_grade g

3    ON trunc((sysdate-e.birthday)/365,0) BETWEEN g.s_age AND g.e_age ;



3. OUTER Join



오라클 아우터 조인은 Where 조건절에서 데이터가 없는 쪽에 (+) 표시를 추가

ANSI 아우터 조인구문에서 2번째 행을 보면 LEFT OUTER JOIN 이라는 구문이 있는데

ANSI 아우터 조인에서는 데이터가 존재하는 쪽에 표시를 하기 때문에 이런 구문을 사용  



Outer Join 예제 2 :

Student 테이블과 Professor 테이블을 Join 하여 학생이름과 지도교수 이름을 출력하세요.

단 지도학생이 결정 안 된 교수 명단과 지도 교수가 결정 안된 학생 명단을 한꺼번에 출력하세요.


- Oracle Outer Join 구문 :

SCOTT>SELECT s.name "학생이름" , p.name "교수이름"

2    FROM student s , professor p

3    WHERE s.profno(+) = p.profno

4    UNION

5    SELECT s.name "학생이름" , p.name "교수이름"

6    FROM student s , professor p

7    WHERE s.profno = p.profno(+) ;


- ANSI Full Outer Join 구문 :

SCOTT>SELECT s.name "학생이름" , p.name "교수이름"

2    FROM student s FULL OUTER JOIN professor p

3    ON s.profno = p.profno ;



4. SELF Join

하나의 테이블에 있는 데이터를 JOIN 하는 방법


SELF Join 예 )  dept2 테이블에서 DNAME 은 부서명 , PDEPT는 상위부서 입니다.

출력 하고자 하는 형태가 "경영지원부의 상위부서는 사장실이다" 라는 형태일 경우 원하는 데이터가 모두 dept2 

테이블에 있기 때문에 SELF 조인을 사용


왼쪽 테이블의 PDEPT 번호와 오른쪽 테이블의 DCODE 번호가 같은 부서가 상위부서 명입니다.

- Oracle Join 구문 :

SCOTT>SELECT a.dname "부서명" , b.dname "상위부서명"

2    FROM dept2 a , dept2 b

3    WHERE a.pdept = b.dcode ;


- ANSI Join 구문 :

SCOTT>SELECT a.dname "부서명" , b.dname "상위부서명"

2    FROM dept2 a JOIN dept2 b

3    ON a.pdept = b.dcode ;





- Oracle Join 구문 :

SCOTT>SELECT p.profno "교수번호" , p.name "교수명" , p.hiredate "입사일" , count(b.hiredate) "빠른사람"

2    FROM professor p , professor b

3    WHERE p.hiredate > b.hiredate (+)

4    GROUP BY p.profno , p.name, p.hiredate

5    ORDER BY 4 ;


- ANSI Join 구문 :

SCOTT>SELECT p.profno "교수번호" , p.name "교수명" , p.hiredate "입사일" , count(b.hiredate) "빠른사람"

2    FROM professor p LEFT OUTER JOIN professor b

3    ON p.hiredate > b.hiredate 

4    GROUP BY p.profno , p.name, p.hiredate

5    ORDER BY 4 ;

- Oracle Join 구문 :

SCOTT>SELECT a.empno "사원번호" , a.name "사원명" , a.hiredate "입사일" , count(b.hiredate) "먼저입사한사람수"

2    FROM emp a , emp b

3    WHERE a.hiredate > b.hiredate (+) 

4    GROUP BY a.empno , a.name, a.hiredate

5    ORDER BY 4 ;


- ANSI Join 구문 :

SCOTT>SELECT a.empno "사원번호" , a.name "사원명" , a.hiredate "입사일" , count(b.hiredate) "먼저입사한사람수"

2    FROM emp a LEFT OUTER JOIN emp b

3    ON a.hiredate > b.hiredate (+) 

4    GROUP BY a.empno , a.name, a.hiredate

5    ORDER BY 4 ;


반응형

'오라클 > SQL' 카테고리의 다른 글

sql 쿼리결과를 파일로 저장  (0) 2015.07.03
DML  (0) 2014.10.12
DDL  (0) 2014.10.12
그룹함수 (연습문제)  (1) 2014.10.08
복수행 함수 (그룹 함수)  (1) 2014.10.08
sql 단일행 함수 - 정규식  (2) 2014.10.01
sql 단일행 함수 - 일반 함수  (0) 2014.09.30
반응형

1. Professor 테이블을 사용하여 교수 중에서 급여(Pay) 와 보너스(bonus)를 합친 금액이 가장 많은 경우와 가장 적은 경우, 

평균 금액을 구하세요. 단 보너스가 없을 경우는 보너스를 0 으로 계산하고 출력 금액은 모두 소수점 첫째 자리까지만 출력


2. Professor 테이블을 사용하여 교수 중에서 급여(Pay) 와 보너스(bonus)를 합친 금액이 가장 많은 경우와 가장 적은 경우, 

평균 금액을 구하세요. 단 보너스가 없을 경우는 급여를 0 으로 계산하고 출력 금액은 모두 소수점 첫째 자리까지만 출력


3. student 테이블의 birthday 컬럼을 사용하여 아래와 같이 월별로 태어난 인원수를 출력

4. emp 테이블의 hiredate 컬럼을 참조해서 아래와 같이 월별로 입사인원수를 출력


5. student 테이블의 tel 컬럼을 참고하여 아래와 같이 지역별 인원수를 출력 

 단 02-서울, 031-경기, 051-부산 , 052-울산, 053-대구, 055-경남으로 출력


6. 먼저 emp 테이블에 아래의 두 건의 데이터를 입력 하신 후 작업하세요.

emp테이블을 사용하여 아래의 화면과 같이 부서별로 직급별로 급여 합계 결과를 출력

SQL>insert into emp(empno,deptno,ename,sal)

 2 values (1000,10,'홍길동',3600);


SQL>insert into emp(empno,deptno,ename,sal)

 2 values (2000,30,'일지매',3000);


SQL>commit;


7. emp 테이블을 사용하여 직업들의 급여와 누적급여 금액이 아래와 같도록 출력

 단 급여를 오름차순으로 정렬해서 출력


8. fruit테이블을 아래와 같은 형태로 출력


9. student 테이블의 tel컬럼을 사용하여 아래와 같이 지역별 인원수와 전체대비 차지하는 비율을 출력

(단 ,02-서울, 031-경기, 051-부산 , 052-울산, 053-대구, 055-경남으로 출력)


10. emp 테이블을 사용하여 아래와 같이 부서별로 급여 누적 합계가 나오도록 출력

 단 부서번호로 오름차순 출력


11. emp 테이블을 사용하여 아래와 같이 각 사원의 급여액이 전체 직원 급여총액에서 몇%의 비율을 차지하는지 출력 

 단 급여 비중이 높은 사람이 먼저 출력되도록 하시오


12. emp 테이블을 조회하여 아래와 같이 각 직원들의 급여가 해당 부서 합계금액에서 몇 %의 비중을 차지하는지를 출력

 단 부서번호를 기준으로 오름차순으로 출력



반응형

'오라클 > SQL' 카테고리의 다른 글

DML  (0) 2014.10.12
DDL  (0) 2014.10.12
JOIN 함수  (0) 2014.10.10
복수행 함수 (그룹 함수)  (1) 2014.10.08
sql 단일행 함수 - 정규식  (2) 2014.10.01
sql 단일행 함수 - 일반 함수  (0) 2014.09.30
sql 단일행 함수 - 형 변환 함수  (1) 2014.09.30

+ Recent posts