6. 조합 데이터 유형

 

※ PL/SQL Record

DECLARE

 TYPE emp_rec_typ IS RECORD              --레코드 구조체. 필드는 둘 이상.

 ( ename VARCHAR2(10),

      sal emp.sal%TYPE,

      job emp.job%TYPE := 'NONE' ) ;

  emp_rec   EMP_REC_TYP ;

 

BEGIN

 SELECT ename, sal, job INTO emp_rec

 FROM emp

 WHERE empno = 7788 ;

 

END ;

/

PL/SQL procedure successfully completed.

 

※ %ROWTYPE 사용

 

DECLARE

  emp_rec emp%ROWTYPE ; --테이블 emp의 이름 및 유형을 가져온다.

BEGIN

  SELECT * INTO emp_rec FROM emp WHERE empno = 7788 ;

END ;

/

PL/SQL procedure successfully completed.

 

 

DECLARE

  emp_rec emp%ROWTYPE ;  --테이블,뷰이름%ROWTYPE

BEGIN

  SELECT * INTO emp_rec FROM emp WHERE empno = 7788 ;

  INSERT INTO copy_emp VALUES emp_rec ;

  SELECT * INTO emp_rec FROM emp WHERE empno = 7782 ;

  emp_rec.sal      := emp_rec.sal * 1.2 ;

  emp_rec.hiredate := SYSDATE ;

  UPDATE copy_emp SET ROW = emp_rec WHERE empno = 7782 ;

END ;

  /

PL/SQL

PROCEDURE successfully completed.


#추가해야함.





'ORACLE > PL/SQL' 카테고리의 다른 글

8장 .예외처리  (0) 2014.02.16
7장. 명시적 커서 사용  (0) 2014.02.16
5장. 제어 구조 작성  (0) 2014.02.16
4장 PL/SQL 프로그램에서 SQL 문과 상호 작용  (0) 2014.02.16
3장 실행문 작성  (0) 2014.02.16

1.IF

ex1)

SET SERVEROUTPUT ON

DECLARE

             v_myage NUMBER := 10 ;

BEGIN

             IF v_myage < 11 THEN

              DBMS_OUTPUT.PUT_LINE(' I am a child ');

             END IF;

END;

/

 I am a child

PL/SQL procedure successfully completed.

 

ex2)

DECLARE

             v_myage NUMBER := 31 ;

BEGIN

             IF v_myage < 11 THEN

              DBMS_OUTPUT.PUT_LINE(' I am a child ');

             ELSE

              DBMS_OUTPUT.PUT_LINE(' I am not a child ');

             END IF;

END;

/

I am not a child

PL/SQL procedure successfully completed.

 

 

Ex3) 초기화가 되지 않은 변수에대한 IF

DECLARE

             v_myage NUMBER ;

BEGIN

             IF v_myage < 11 THEN

              DBMS_OUTPUT.PUT_LINE(' I am a child ');

             ELSE

              DBMS_OUTPUT.PUT_LINE(' I am not a child ');

             END IF;

END;

/

I am not a child

PL/SQL procedure successfully completed.

 

-> NULL은 비교가 불가 하므로 ELSE로 넘어가서 I am not a child 출력.

 

 

Ex4) ELSIF

 

DECLARE

             v_myage NUMBER := 31 ;

BEGIN

             IF v_myage < 11 THEN

              DBMS_OUTPUT.PUT_LINE(' I am a child ');

             ELSIF v_myage < 20 THEN

              DBMS_OUTPUT.PUT_LINE(' I am young ');

             ELSIF v_myage < 30 THEN

              DBMS_OUTPUT.PUT_LINE(' I am in my twenties');

             ELSIF v_myage < 40 THEN

               DBMS_OUTPUT.PUT_LINE(' I am in my thirties');

             ELSE

               DBMS_OUTPUT.PUT_LINE(' I am always young ');

END IF;

END;

/

I am in my thirties

PL/SQL procedure successfully completed.

 

2. CASE 표현식 값을 할당할때, 또 다른 명령을 실행시킬때 사용


ex1)값을 할당할 때 

DECLARE

             v_grade CHAR(1) := UPPER('&grade') ;

             v_appraisal VARCHAR2(20) ;

BEGIN

             v_appraisal := CASE v_grade WHEN 'A' THEN 'Excellent'

                                                                   WHEN 'B' THEN 'Very Good'

                                                                   WHEN 'C' THEN 'Good'

                                                                   ELSE 'No such grade'

                                                                   END;

             DBMS_OUTPUT.PUT_LINE ('Grade: '|| v_grade || ' Appraisal ' || v_appraisal);

END;

/

 Enter value for grade: B

old 2: v_grade CHAR(1) := UPPER('&grade') ;

new 2: v_grade CHAR(1) := UPPER('B') ;

 Grade: B Appraisal Very Good

PL/SQL procedure successfully completed.

  

 ex2)또 다른 명령어를 실행하기 위한 CASE문

DECLARE

             v_sum NUMBER ;

             v_deptno NUMBER := &deptid ;

BEGIN

             CASE v_deptno

             WHEN 10 THEN

                           SELECT SUM(sal) INTO v_sum

                           FROM emp

                           WHERE deptno = 10 ;

             WHEN 20 THEN

                           SELECT SUM(sal) INTO v_sum

                           FROM emp

                           WHERE deptno = 20 ;

             WHEN 30 THEN

                           SELECT SUM(sal) INTO v_sum

                           FROM emp

                           WHERE deptno = 30 ;

             ELSE

                           SELECT SUM(sal) INTO v_sum FROM emp ;

             END CASE ;

DBMS_OUTPUT.PUT_LINE ( v_sum ) ;

END ;

/

 Enter value for deptid: 30

old 3: v_deptno NUMBER := &deptid ;

new 3: v_deptno NUMBER := 30 ;

 9400

PL/SQL procedure successfully completed.

 

3. Loop : 반복수행


EX1) Basic Loop

SQL> SET SERVEROUTPUT ON

DECLARE

             v_count NUMBER(2) := 1 ;

BEGIN

             LOOP

                           DBMS_OUTPUT.PUT_LINE ('count: '||to_char(v_count)) ;

                           v_count := v_count + 1 ;

                           EXIT WHEN v_count = 4 ;

             END LOOP ;

END;

/

 

count: 1

count: 2

count: 3

PL/SQL procedure successfully completed.

 

Ex2) While Loop

BEGIN

 WHILE v_count <= 3 

 LOOP

  DBMS_OUTPUT.PUT_LINE ('count: '||to_char(v_count)) ;

  v_count := v_count + 1 ;

 END LOOP ;

END ;

/

count: 1

count: 2

count: 3

PL/SQL procedure successfully completed.

 

Ex3) For Loop, 반복 횟수를 알고있을 때 사용

BEGIN

 FOR i IN 1..3 

 LOOP  

  DBMS_OUTPUT.PUT_LINE ('count: '||to_char(i)) ;

 END LOOP ;

END ;

/

count: 1

count: 2

count: 3

PL/SQL procedure successfully completed

 

Ex4)For  Loop는 암시적으로 카운터가 생긴다.

BEGIN

 FOR i IN 1..3 LOOP

  DBMS_OUTPUT.PUT_LINE ('count: '||to_char(i)) ;

 END LOOP ;

END ;

/

count: 1

count: 2

count: 3

PL/SQL procedure successfully completed

 

Ex5)  Reverse For Loop 거꾸로연산.

BEGIN

 FOR i IN REVERSE 1..3 

  LOOP

   DBMS_OUTPUT.PUT_LINE ('count: '||to_char(i)) ;

  END LOOP ;

END ;

/

count: 3

count: 2

count: 1

PL/SQL procedure successfully completed.

 

※ Nested Loops  중첩된 Loop를 빠져나갈때 Exit

DECLARE

  x NUMBER := 3 ;

  y NUMBER ;

BEGIN

  <<OUTER_LOOP>>

  LOOP

    y := 1 ;

    EXIT WHEN x > 5 ;

       <<INNER_LOOP>>

             LOOP

                DBMS_OUTPUT.PUT_LINE ( x || ' * ' || y || ' = ' || x * y ) ;

                y := y + 1 ;

                EXIT WHEN y > 5 ;

             END LOOP INNER_LOOP ;

    x := x + 1 ;

 END LOOP OUTER_LOOP ;

END ;

/

 

 

3 * 1 = 3

3 * 2 = 6

3 * 3 = 9

3 * 4 = 12

3 * 5 = 15

4 * 1 = 4

4 * 2 = 8

4 * 3 = 12

4 * 4 = 16

4 * 5 = 20

5 * 1 = 5

5 * 2 = 10

5 * 3 = 15

5 * 4 = 20

5 * 5 = 25

PL/SQL procedure successfully completed.

 

 

 DECLARE

x NUMBER := 3 ;

y NUMBER ;

BEGIN

<<OUTER_LOOP>>

LOOP

y := 1 ;

EXIT WHEN x > 5 ;

<<INNER_LOOP>>

LOOP

DBMS_OUTPUT.PUT_LINE ( x || ' * ' || y || ' = ' || x * y ) ;

EXIT OUTER_LOOP WHEN x*y > 15 ;

y := y + 1 ;

EXIT WHEN y > 5 ;

END LOOP INNER_LOOP ;

x := x + 1 ;

END LOOP OUTER_LOOP ;

END ;

/

 

4. CONTINUE :

11g부터 생긴것. Continue에 만족하는 사항이 생기면, 밑에 있는 것은 싫행하지말고첫번째 시퀀스부터 다시 시작함.

ex1)

SQL> SET SERVEROUTPUT ON

DECLARE

             v_total SIMPLE_INTEGER := 0;

BEGIN

             FOR i IN 1..5 LOOP

              v_total := v_total + i;

              DBMS_OUTPUT.PUT_LINE ('Total is: '|| v_total) ;

              CONTINUE WHEN i > 3 ;

              v_total := v_total + i;

              DBMS_OUTPUT.PUT_LINE ('Out of Loop Total is: '|| v_total);

             END LOOP;

END;

/

 Total is: 1 <= 0 + 1 (i)

Out of Loop Total is: 2 <= 1 + 1 (i)

Total is: 4 <= 2 + 2 (i)

Out of Loop Total is: 6 <= 4 + 2 (i)

Total is: 9 <= 6 + 3 (i)

Out of Loop Total is: 12 <= 9 + 3 (i)

Total is: 16 <= 12 + 4 (i)

Total is: 21 <= 16 + 5 (i)

PL/SQL procedure successfully

 

ex2)

SQL> SET SERVEROUTPUT ON

DECLARE

  v_total NUMBER := 0;

BEGIN

  <<BeforeTopLoop>>

  FOR i IN 1..5

  LOOP

    v_total := v_total + 1;

    DBMS_OUTPUT.PUT_LINE ('Outer Total is: ' || v_total) ;

    FOR j IN 1..5

    LOOP

      CONTINUE BeforeTopLoop

    WHEN i               + j > 5 ;

      v_total := v_total + 1;

      DBMS_OUTPUT.PUT_LINE ('Inner Total is: ' || v_total) ;

    END LOOP;

  END LOOP;

END ;

/

Outer Total is: 1 <= 0 + 1 (i=1)

Inner Total is: 2 <= 1 + 1 (i=1 , j=1)

Inner Total is: 3 <= 2 + 1 (i=1 , j=2)

Inner Total is: 4 <= 3 + 1 (i=1 , j=3)

Inner Total is: 5 <= 4 + 1 (i=1 , j=4)

Outer Total is: 6 <= 5 + 1 (i=2)

Inner Total is: 7 <= 6 + 1 (i=2 , j=1)

Inner Total is: 8 <= 7 + 1 (i=2 , j=2)

Inner Total is: 9 <= 8 + 1 (i=2 , j=3)

Outer Total is: 10 <= 9 + 1 (i=3)

Inner Total is: 11 <= 10 + 1 (i=3 , j=1)

Inner Total is: 12 <= 11 + 1 (i=3 , j=2)

Outer Total is: 13 <= 12 + 1 (i=4)

Inner Total is: 14 <= 13 + 1 (i=4 , j=1)

Outer Total is: 15 <= 14 + 1 (i=5)

PL/SQL procedure successfully completed.

 

'ORACLE > PL/SQL' 카테고리의 다른 글

7장. 명시적 커서 사용  (0) 2014.02.16
6장 . 조합데이터 유형  (0) 2014.02.16
4장 PL/SQL 프로그램에서 SQL 문과 상호 작용  (0) 2014.02.16
3장 실행문 작성  (0) 2014.02.16
2장 PL/SQL 변수 선언  (0) 2014.02.16

4장. PL/SQL 프로그램에서 SQL 문과 상호 작용


# SQL/PLSQL 호출범위

SQL

-         QUERY  : SELECT

-         DML      : Insert / Update / Delete / Merge

-         TCL       : COMMIT / ROLLBACK / SAVEPOINT                          PL/SQL은 여기까지만 허용한다.

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

-         DCL      : GRANT /  REVOKE / 

-         DDL      : CREATE / DROP / ALTER / TRUNBCATE / RENAME  PL/SQL에서 호출 불가능.

 

DML( INSERT, UPDATE, DELETE )

사용자가 명시적으로 COMMIT을 하지 않는다면 COMMIT되지 않는다.

실제 PL/SQL을 업무에서 사용한다면 PL/SQL 블럭 내에 COMMIT ; 을 넣어준다.


ex1) INSERT

BEGIN

             INSERT INTO emp(empno, ename, sal, deptno)

             VALUES (1234, 'RYU', 3000, 20) ;

END ;

/

PL/SQL procedure successfully completed.

 

BEGIN

             UPDATE emp

             SET sal = 4000

             WHERE empno = 1234 ;

END ;

/

PL/SQL procedure successfully completed.

 

Ex2) DELETE

BEGIN

             DELETE emp

             WHERE empno = 1234 ;

END ;

/

PL/SQL procedure successfully completed.

DELETE사용시 완료가 되었다는 결과 확인만으로  1234가 있어서 영향을 받았는지, 아니면 0행이 지워졌는지 애매하다.


BEGIN

             UPDATE emp

             SET sal = 4000

             WHERE empno = 7788 ;

     

             UPDATE emp

             SET sal = 3500

             WHERE empno = 7566 ;

END ;

/

PL/SQL procedure successfully completed.

 

SELECT empno, sal FROM emp

WHERE empno IN (7788, 7566) ;


EMPNO SAL

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

7566 3500

7788 4000

 

SQL> ROLLBACK ;

 

SQL>

SELECT empno, sal FROM emp

WHERE empno IN (7788, 7566) ;

EMPNO SAL

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

7566 2975

7788 3000


#영향받은 행이 있는지 확인하는 방법.


SQL> SET SERVEROUTPUT ON

BEGIN

             UPDATE emp

             SET sal = 4000

             WHERE empno = 7788 ;

             DBMS_OUTPUT.PUT_LINE ( SQL%ROWCOUNT || ' rows updated') ;

                                                                  --직전 명령 수행에 영향받은 행의 건수 count

             DELETE emp

             WHERE deptno = 10 ;

             DBMS_OUTPUT.PUT_LINE ( SQL%ROWCOUNT || ' rows deleted') ;

END ;

/

1 rows updated

3 rows deleted

 

PL/SQL procedure successfully completed.

 SQL> ROLLBACK ;

  

※ SELECT : - FETCH가 필요하므로 SELECTINTO절이 필요하다.

                    - INTO 절의 변수에 값을 넣는다.

Ex 1)

SQL> SET SERVEROUTPUT ON

DECLARE

             v_ename VARCHAR2(10) ;

             v_sal emp.sal%TYPE ; --참조속성 선언.

BEGIN

             SELECT ename, sal INTO v_ename, v_sal

             FROM emp

             WHERE empno = 7788 ;    --v_ename과 v_sal은 스칼라변수기 떄문에, where 절을 사용하여 하나의 행을 저장해야한다.

             DBMS_OUTPUT.PUT_LINE ( v_ename || ' : ' || v_sal ) ;

END ;

/

 SCOTT : 3000

PL/SQL procedure successfully completed

 

Ex 2) 여러개의 행을 저장해야하므로 Error

SET SERVEROUTPUT ON

DECLARE

             v_ename VARCHAR2(10) ;

             v_sal emp.sal%TYPE ;

BEGIN

             SELECT ename, sal INTO v_ename, v_sal

             FROM emp

             WHERE deptno = 10 ;

             DBMS_OUTPUT.PUT_LINE ( v_ename || ' : ' || v_sal ) ;

END ;

/

ERROR at line 1:

ORA-01422: exact fetch returns more than requested number of rows

ORA-06512: at line 5

 

Ex  3)검색된 행이 없는 Error

SQL> SET SERVEROUTPUT ON

DECLARE

             v_ename VARCHAR2(10) ;

             v_sal emp.sal%TYPE ;

BEGIN

             SELECT ename, sal INTO v_ename, v_sal

             FROM emp

             WHERE empno = 1111 ;

             DBMS_OUTPUT.PUT_LINE ( v_ename || ' : ' || v_sal ) ;

END ;

/

ERROR at line 1:

ORA-01403: no data found

ORA-06512: at line 5

 

※ DDL, DCL PL/SQL에서 호출 불가능.

BEGIN

             DROP TABLE emp ;

END ;

/

ERROR at line 2:

ORA-06550: line 2, column 3:

PLS-00103: Encountered the symbol "DROP" when expecting one of the following:

( begin case declare exit for goto if loop mod null pragma raise return select update while with <an

identifier> <a double-quoted delimited-identifier> <a bind variable> <<continue close current delete

fetch lock insert open rollback

savepoint set sql execute commit forall merge pipe purge

 

 

#참고

SYS@ORCL>show parameter cursor; 

NAME                                    TYPE        VALUE

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

cursor_sharing                       string        EXACT

cursor_space_for_time            boolean     FALSE

open_cursors                         integer         50

        --동시에 오픈 할 수 있는 커서 50. (명시적커서)

session_cached_cursors               integer     50

--50개저장.


 

내 세션에서 만약 SQL이 실행 되었다면 별도의 공간(Closed Cuosor)에 실행계획을 저장하여 Library Cache를 들어가지 않고 확인한다.

명시적 커서를 이용하면 PL/SQL에서 조건에 맞는게 둘 이상 나올 경우 중간에 하나씩 하나씩 끊어갈 수 있다.

'ORACLE > PL/SQL' 카테고리의 다른 글

6장 . 조합데이터 유형  (0) 2014.02.16
5장. 제어 구조 작성  (0) 2014.02.16
3장 실행문 작성  (0) 2014.02.16
2장 PL/SQL 변수 선언  (0) 2014.02.16
1장. PL/SQL 소개  (0) 2014.02.16

 1. PL/SQL 에서의 함수 사용

 

ex1)단일행 함수 사용.

SET SERVEROUTPUT ON

 DECLARE

                v_desc_size INTEGER(5);

                v_prod_description VARCHAR2(70) := 'You can use this product with your radios for higher frequency';

 BEGIN

                v_desc_size := LENGTH(v_prod_description) ;

                DBMS_OUTPUT.PUT_LINE (v_desc_size) ;

END ;

/

 62

PL/SQL procedure successfully completed.

 

ex2)그룹함수는 scalar type에 사용될 수 없다.

DECLARE

                v_desc_size INTEGER(5);

                v_prod_description VARCHAR2(70) := 'You can use this product with your radios for higher frequency';

BEGIN

                v_desc_size := MAX(v_prod_description) ;

                DBMS_OUTPUT.PUT_LINE (v_desc_size) ;

END ;

/

ERROR at line 5:

ORA-06550: line 5, column 18:

PLS-00204: function or pseudo-column 'MAX' may be used inside a SQL statement only

ORA-06550: line 5, column 3:

PL/SQL: Statement ignored

 

ex3)그룹함수가 SELECT 명령어와 함께 쓰이면 사용가능하다.

DECLARE

         v_sum NUMBER ;

BEGIN

         SELECT SUM(sal) INTO v_sum

FROM emp ;

                DBMS_OUTPUT.PUT_LINE (v_sum) ;

END ;

/

29025

PL/SQL procedure successfully completed.

 

2. PL/SQL 에서 SEQUENCE 사용

 

ex1) 11g부터 제공됨.

SQL> CREATE SEQUENCE empno_seq START WITH 1000 ;

SQL> SET SERVEROUTPUT ON

DECLARE

                v_num NUMBER := empno_seq.NEXTVAL ;

BEGIN

                DBMS_OUTPUT.PUT_LINE ( v_num ) ;

END ;

/

 1000

 

ex2)

DECLARE

                 v_num NUMBER ;

BEGIN

                SELECT empno_seq.NEXTVAL INTO v_num

                FROM dual ;

                DBMS_OUTPUT.PUT_LINE ( v_num ) ;

END ;

/

1001

PL/SQL procedure successfully completed.

 

중첩 블록에서 변수의 범위

 

ex1) 상위 블럭에서 선언된 변수는 하위변수에서 참조가 가능하다.

SET SERVEROUTPUT ON

DECLARE

                v_outer VARCHAR2(100) := 'Outer Variable' ;

BEGIN

                DBMS_OUTPUT.PUT_LINE ('Outer : ' || v_outer ) ;

                           DECLARE

                                       v_inner VARCHAR2(100) := 'Inner Variable' ;

                           BEGIN

                                        DBMS_OUTPUT.PUT_LINE ('Outer : ' || v_outer ) ;

                                        DBMS_OUTPUT.PUT_LINE ('Inner : ' || v_inner) ;

                        END ;

DBMS_OUTPUT.PUT_LINE ('Outer : ' || v_outer ) ;

END ;

/

 

Outer : Outer Variable

Outer : Outer Variable

Inner : Inner Variable

Outer : Outer Variable

 

ex2)하위 블록에 선언된 변수는 상위변수에서 출력 불가능하다.

SQL> SET SERVEROUTPUT ON

DECLARE

             v_outer VARCHAR2(100) := 'Outer Variable' ;

BEGIN

             DECLARE

                           v_inner VARCHAR2(100) := 'Inner Variable' ;

             BEGIN

                           DBMS_OUTPUT.PUT_LINE ('Outer : ' || v_outer ) ;

             DBMS_OUTPUT.PUT_LINE ('Inner : ' || v_inner) ;

END ;

             DBMS_OUTPUT.PUT_LINE ('Outer : ' || v_outer ) ;

             DBMS_OUTPUT.PUT_LINE ('Inner : ' || v_inner) ;

 END ;

/

ERROR at line 11:

ORA-06550: line 11, column 39:

PLS-00201: identifier 'V_INNER' must be declared

ORA-06550: line 11, column 3:

PL/SQL: Statement ignored

 

Ex3) 같은 변수이름으로 만들 경우, 레이블을 통한 구분.

BEGIN <<outer>> --테이블에 별칭을 붙이듯 레이블을지정.

             DECLARE

                           v_father_name VARCHAR2(20):='Patrick';

                           v_date_of_birth DATE := TO_DATE('20-APR-1972','DD-MON-YYYY') ;

             BEGIN

                           DECLARE           

                                        v_child_name VARCHAR2(20):='Mike';

                                        v_date_of_birth DATE := TO_DATE('12-DEC-2002','DD-MON-YYYY') ;

                           BEGIN

                                        DBMS_OUTPUT.PUT_LINE('Father''s Name: '||v_father_name);

                                        DBMS_OUTPUT.PUT_LINE('Date of Birth: '||outer.v_date_of_birth);

                                        DBMS_OUTPUT.PUT_LINE('Child''s Name: '||v_child_name);

                                        DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);

                           END;

             END;

END outer;

/

Father's Name: Patrick

Date of Birth: 20-APR-72

Child's Name: Mike

Date of Birth: 12-DEC-02

PL/SQL procedure successfully completed.

'ORACLE > PL/SQL' 카테고리의 다른 글

6장 . 조합데이터 유형  (0) 2014.02.16
5장. 제어 구조 작성  (0) 2014.02.16
4장 PL/SQL 프로그램에서 SQL 문과 상호 작용  (0) 2014.02.16
2장 PL/SQL 변수 선언  (0) 2014.02.16
1장. PL/SQL 소개  (0) 2014.02.16

변수

 1.스칼라 데이터 (단일값 변수)  :한번에 하나의 행이 하나의 컬럼의 값.( 보통 “V_컬럼의 이름이용.)


DECLARE  -- 선언부 

 V_EMPNO    NUMBER(4);

 V_ENAME    VARCHAR2(10);

 V_SAL         NUMBER(7,2) ;

 V_DEPTNO  NUMBER (2);

BEGIN

  SELECT EMPNO,ENAME,SAL,DEPTNO

       INTO V_EMPNO,V_ENAME,V_SAL,V_DEPTNO

  FROM EMP 

 -- WHERE EMPNO = 7788;

END ;

/

→  이 경우 ERROR 발생한다. 단일행 변수는 하나의 행만 저장 가능하다.

A. 적절한 where절을 통해 반드시 한개의 행만 검색되도록 해야한다

 

Q)

DECLARE  

 V_EMPNO    NUMBER(4);

 V_ENAME    VARCHAR2(10);

 V_SAL         NUMBER(7,2) ;

 V_DEPTNO  NUMBER (2);

BEGIN

  SELECT EMPNO,ENAME,SAL,DEPTNO

       INTO V_EMPNO,V_ENAME,V_SAL,V_DEPTNO

  FROM EMP

  WHERE EMPNO = 1234;

END ;

/

A..조건에 맞는 1234 행이 없으므로 ERROR발생한다.


DECLARE 

 V_EMPNO    NUMBER(4)  := 1234;                  -- 할당 연산자 :=  를 통한 변수에 값 할당.

 V_ENAME    VARCHAR2(10) DEAFULT 'ABCD'; -- DEFAULT 를 통한 할당.

 V_SAL         NUMBER(7,2) ;

 V_DEPTNO  NUMBER (2); 

BEGIN

  V_EMPNO :=1234  ;

  V_ENAME :='ABCD';

END ;

/ 


# 변수선언

SQL>

SET SERVEROUTPUT ON

DECLARE

 v_hiredate DATE ;  -- 초기값이 없다면 기본 NULL을 가지고 시작한다.

                              -- (초기값이 없는것에 NOT NULL제약조건 사용할 수 없다.)

 v_deptno NUMBER(2) NOT NULL := 10 ;  -- NOT NULL 제약조건

 v_location VARCHAR2(13) := 'Atlanta';  

c_comm CONSTANT NUMBER := 1400 ;   -- CONSTANT를 통해 상수선언실행부에서 값을 수정불가.

BEGIN

 DBMS_OUTPUT.PUT_LINE ( v_hiredate ) ; 

 DBMS_OUTPUT.PUT_LINE ( v_deptno ) ; 

 DBMS_OUTPUT.PUT_LINE ( v_location ) ;

 DBMS_OUTPUT.PUT_LINE ( c_comm ) ;

END ;

/


# PL/SQL 에서 Date type의 주의 사항

SQL> ALTER SESSION SET nls_date_format = 'DD-MON-RR' ;

SQL> SET SERVEROUTPUT ON

DECLARE

 v_hiredate DATE := '09-DEC-13' ;

BEGIN

 DBMS_OUTPUT.PUT_LINE ( v_hiredate ) ;

END ;

/

 09-DEC-13

PL/SQL procedure successfully completed.

 

SQL> ALTER SESSION SET nls_date_format = 'RR/MM/DD' ;

SQL> SET SERVEROUTPUT ON

DECLARE

 v_hiredate DATE := '09-DEC-13' ;

BEGIN

 DBMS_OUTPUT.PUT_LINE ( v_hiredate ) ;

END ;

/

 09/12/13 << 올바른 값인가?

13년 12월 9일인지, 09년 12월 13일인지 애매하다.

PL/SQL procedure successfully completed.

 

A.해결: TO_DATE를 통한 형변환

SQL> ALTER SESSION SET nls_date_format = 'RR/MM/DD' ;

SQL> SET SERVEROUTPUT ON

DECLARE

 v_hiredate DATE := TO_DATE('09-DEC-13','DD-MON-RR') ;

BEGIN

 DBMS_OUTPUT.PUT_LINE ( v_hiredate ) ;

END ;

/

13/12/09

PL/SQL procedure successfully completed.

 SQL> ALTER SESSION SET nls_date_format = 'DD-MON-RR' ;

 

날짜는 날짜의 포멧의 영향을 받는다. TO_DATE를 통해 형변환을 하여 엉뚱한 값이 나오지 않게 한다.


# BINARY_FLOAT, BINARY_DOUBLE type 확인

SQL> SET SERVEROUTPUT ON

DECLARE

 bf_var binary_float ;

 bd_var binary_double ;

BEGIN

 bf_var := 270/35 ;

 bd_var := 140/0.35 ;

DBMS_OUTPUT.PUT_LINE ('bf: ' || bf_var );

DBMS_OUTPUT.PUT_LINE ('bd: ' || bd_var );

END ;

/

 bf: 7.71428585E+000

 bd: 4.0E+002

PL/SQL procedure successfully completed.


SQL> SET SERVEROUTPUT ON

DECLARE

 bf_var NUMBER ;

 bd_var NUMBER ;

BEGIN

 bf_var := 270/35 ;

 bd_var := 140/0.35 ;


 DBMS_OUTPUT.PUT_LINE ('bf: ' || bf_var );

 DBMS_OUTPUT.PUT_LINE ('bd: ' || bd_var );

END ;

/


bf: 7.71428571428571428571428571428571428571

bd: 400

PL/SQL procedure successfully completed


# %TYPE 사용

 –이점: 참조하는 테이블/컬럼의 구조적인 변경이 있을경우 수정을 해야하는데, %TYPE을 사용하면 변경하지 않아도 된다.

 

SQL> SET SERVEROUTPUT ON

DECLARE

 v_sal emp.sal%TYPE ;

BEGIN

 SELECT sal INTO v_sal

 FROM emp

 WHERE empno = 7788 ;


 DBMS_OUTPUT.PUT_LINE ( v_sal ) ;

END ;

/

 3000

PL/SQL procedure successfully completed.


# Bind Variable 사용

--호출환경에서 선언된 변수Sqlplus, sqldeveloper 에서 선언.


SQL> VARIABLE b_sal NUMBER

SQL> PRINT b_sal

B_SAL

----------


BEGIN

 SELECT sal INTO :b_sal  -- 호출함수에서 선언된 변수를 출력할 때  :을 붙인다.

 FROM emp

 WHERE empno = 7788 ;

END ;

/

PL/SQL procedure successfully completed.

SQL> PRINT b_sal

B_SAL

----------

3000

'ORACLE > PL/SQL' 카테고리의 다른 글

6장 . 조합데이터 유형  (0) 2014.02.16
5장. 제어 구조 작성  (0) 2014.02.16
4장 PL/SQL 프로그램에서 SQL 문과 상호 작용  (0) 2014.02.16
3장 실행문 작성  (0) 2014.02.16
1장. PL/SQL 소개  (0) 2014.02.16
1장. PL/SQL 소개 ORACLE /PL/SQL 2014. 2. 16. 16:33

1

1. SQL 과 PL/SQL 의 차이


SQL      : 조건 분기 불가능, 루핑 불가능, 변수처리 불가능, 단문 형(화면에 가져와야 그 다음명령실행)

PL/SQL : ORACLE DBMS에서 SQL문장과 제어문을 함게 사용할 수 있다. 코드 실행단위에 블록 구조를 제공한다

              변수, 상수, 데이터타입, 조건문,루프,DB의 객체로 저장가능.


PL/SQL Fundamentals  p1-6그림 중요

 

2. PL/SQL 블럭


SQL> SET SERVEROUTPUT ON            --DBMS_OUT_PUT을 통해 보여주기위함.

DECLARE                                              --선언부( 데이터 이름과 타입 정의)

 emp_rec emp%ROWTYPE ;                   --테이블 구조를 통채로 참조.

 sum_rec emp_sum%ROWTYPE ;

BEGIN

 SELECT * INTO emp_rec                      -- 검색결과를 emp_rec에 저장.

 FROM emp

 WHERE empno = 7788 ;


 DELETE emp

 WHERE empno = 7788 ;

 

 UPDATE emp_sum

 SET sum_sal = sum_sal - emp_rec.sal

 WHERE deptno = emp_rec.deptno ;


 SELECT * INTO sum_rec

 FROM emp_sum

 WHERE deptno = emp_rec.deptno ;


  DBMS_OUTPUT.PUT_LINE ( 'SUM Salary : ' || sum_rec.sum_sal ) ;

END ;

/

SUM Salary : 7875

PL/SQL procedure successfully completed.


SQL         

--PL/SQL에서 수행된 SQL결과는  PL/SQL 블럭으로 리턴된다(보통은 SQL명령을쓴 호출환경에 출력됨.)

 사용자에게 보여주는것은 전체 PL/SQL의 최종결과 즉, 수행 되었는지 안되었는지만 보여준다.

 

이와같은 행동을 반복할 때 귀찮으므로 PROCEDURE 라는 것이 있다.

 

3. Procedure 생성   마치 뷰,테이블 등을 만드는 것 처럼 DB의 객체를 생성하는것이다.

 

CREATE OR REPLACE PROCEDURE delete_emp

 ( p_empno NUMBER) AS

 emp_rec emp%ROWTYPE ;

 sum_rec emp_sum%ROWTYPE ;

BEGIN

 SELECT * INTO emp_rec

 FROM emp

 WHERE empno = p_empno ;


 DELETE emp

 WHERE empno = p_empno ;


 UPDATE emp_sum

 SET sum_sal = sum_sal - emp_rec.sal

 WHERE deptno = emp_rec.deptno ;


 SELECT * INTO sum_rec

 FROM emp_sum

 WHERE deptno = emp_rec.deptno ;


 DBMS_OUTPUT.PUT_LINE ( 'SUM Salary : ' || sum_rec.sum_sal ) ;

END ;

/

Procedure created.

 

SQL> SET SERVEROUTPUT ON   -- DBMS.OUTPUT은 기본값이 OFF이므로 켜야한다.

SQL> EXECUTE delete_emp (7788)

 SUM Salary : 7875

PL/SQL procedure successfully completed.

 

SQL> ROLLBACK ;

 

'ORACLE > PL/SQL' 카테고리의 다른 글

6장 . 조합데이터 유형  (0) 2014.02.16
5장. 제어 구조 작성  (0) 2014.02.16
4장 PL/SQL 프로그램에서 SQL 문과 상호 작용  (0) 2014.02.16
3장 실행문 작성  (0) 2014.02.16
2장 PL/SQL 변수 선언  (0) 2014.02.16