본문 바로가기

Oracle/오라클 양성반 15기

composite data type , cursor

PL/SQL

(미리말하지만 ㅡ_ㅡ;; 전 글재주가 없습니다.)

/**************************************************************************/

 

composite data type

 

기본적인 하나의 데이터 타입 ( 스칼라 데이터 타입 )
1개이상의 데이터를 묶어서 만든 데이터 타입

 

============ Record ============

* Record : 하나이상의 기본 자료형을 모아서 만든 사용자 정의 데이터 타입.
(개발언어에서의 클래스 , type, 구조체와 비슷함)

 

 

    A. 기본구문 :   
       Type type_name IS RECORD
        (column_name1, column_name2,column_name3 ... );
       
    B. 예 :
        TYPE emp_record_type IS RECORD
            (last_name  varchar(25),
             job_id     varchar(10),
             salary     number(10));
       
        (레코드변수)    (레코드 타입)
        emp_record      emp_record_type;  
       
   
    C. 사용방법 :
       
        emp_recor.last_name  := '홍길동';
        emp_recor.job_id     := 'job';
        emp_recor.salary     := 15000;
       
        ※ last_name, job_id, salary 는 "멤버" 라고 함.
   
   
    D. 작성순서 :
        1. 레코드 타입 정의.
        2. 레코드 변수 정의.
        3. 멤버변수에 값을 할당. ( memory write )
        4. 멤버변수값 활용. ( memory read )
   
    E. 관련 연습 문제 :
   
        문제)
        레코드 타입으로 사원의 사번, 이름, 입사일자를 출력하는 프로그램을 작성하시오.
        단, 사번은 치환 변수를 사요하시오.
       
        출력예시
            Emp# : 7788
            Emp_name : SCOTT
            Emp_hiredate : 87/04/19
           
       
        답)
        SQL>conn scott/tiger
        SQL>set serveroutput on
       
        SQL>
        declare
      
            /**************************************************
                --레코드 변수 기본구문
               
                TYPE 레코드이름 IS RECORD
                (
               
                );
            **************************************************/
           
            TYPE emp_record IS RECORD
            (
                 v_empno        number,
                 v_ename        varchar(30),
                 v_hiredate     date
            );
           
            emp_rec     emp_record;
          
        begin
                select
                    empno,
                    ename,
                    hiredate
                        into
                        emp_rec.v_empno,
                        emp_rec.v_ename,
                        emp_rec.v_hiredate
                from
                    emp
                where
                    empno = &pempno;
                   
                DBMS_OUTPUT.PUT_LINE('사번 : '||emp_rec.v_empno);
                DBMS_OUTPUT.PUT_LINE('이름 : '||emp_rec.v_ename);
                DBMS_OUTPUT.PUT_LINE('입사일자 : '||emp_rec.v_hiredate);
        end;
        /
       
        결과)       
        Enter value for pempno: 7788
        old  33:                     empno = &pempno;
        new  33:                     empno = 7788;
        사번 : 7788
        이름 : SCOTT
        입사일자 : 1987-04-19 00:00:00
       
        PL/SQL procedure successfully completed.
       
        SQL>

 

 

============ Collection ============

* Collection : 동일한 자료형을 모아놓은 무한 집합체의 개념
(개발언어에서의 array,collection과 비슷한 개념)

 

※ 동일한 자료를 모아놓은 개념은 맞다.

여기서 동일한 자료는 특정데이터형의 여러가지데이터이다.

A. 기본구문 :   

TYPE type_name IS TABLE OF

레코드처럼 원하는 데이터형정의

index by PLS_INTEGER; <----- 이구문은 있어도 되고 없어도 된다.

 

B. 예제 :

declare

    type col_test_value is table of emp.ename%type;
 
    ct_val col_test_value;
   
begin
   
    select
        ename

         
            bulk collect

            into  
            ct_val
    from
        emp;
       
    dbms_output.put_line('ename=>ct_val=>'||ct_val(1) );
    dbms_output.put_line('ename=>ct_val=>'||ct_val(2) );
    dbms_output.put_line('ename=>ct_val=>'||ct_val(3) );
    dbms_output.put_line('ename=>ct_val=>'||ct_val(5) );
  
end;
/

 

 

결과)

ename=>ct_val=>SMITH
ename=>ct_val=>ALLEN
ename=>ct_val=>WARD
ename=>ct_val=>MARTIN

 

bulk collect : 왜  쓰는지는 검색을 해도 좋은 답을 얻지 못했습니다.

개인적인 생각 ( bulk collect 는 보통 데이터를 select해서 가져온 데이터는 보통 PL/SQL 작성시 한행단위로

개발을 하거나 데이터를 저장하고 있는데 이 is table of 같은 것은 데이터를 여러건을

특정 메모리공간에 넣어주어야 하기때문에 그공간을 미리 확보를 해야하기에

그 공간을 확보하겠다는 의미로 보여진다. 그래서 collect 아닐까;;; )

 

안쓰게 되면. ORA-06550 에러 ( sql문에는 로컬 모음이 유형이 허용되지 않음 )

 

※ index 번호는 1번부터 시작.

 

 

예제) 특정테이블 전체의 데이터를 collection 으로 사용가능

 

declare

    type col_test_value is table of emp%rowtype;
 
    ct_val col_test_value;
   
begin
   
    select
        *
            bulk collect
            into  
           
            ct_val
    from
        emp;
       
    dbms_output.put_line('ename=>ct_val=>'||ct_val(1).ename||'---'||ct_val(1).empno);
    dbms_output.put_line('ename=>ct_val=>'||ct_val(2).ename||'---'||ct_val(2).empno);
    dbms_output.put_line('ename=>ct_val=>'||ct_val(3).ename||'---'||ct_val(3).empno);
    dbms_output.put_line('ename=>ct_val=>'||ct_val(5).ename||'---'||ct_val(5).empno);
  
end;
/

 

결과)

ename=>ct_val=>SMITH---7369
ename=>ct_val=>ALLEN---7499
ename=>ct_val=>WARD---7521
ename=>ct_val=>MARTIN---7654

/**************************************************************************/

커서란?

내생각은 아니고 여러군데 검색을 해보면.

- 특정한 sql영역을 가리키는 핸들

- SQL Plus에서 사용자가 실행한 SQL문의 단위를 의미합니다

- 커서는 Private SQL의 작업영역 입니다

- 쿼리문장에 의하여 생성된 데이터 셋트
- 데이터셋트 자체를 cursor 라고 해도 무방.

이런뜻이라고 한다.

 

기본구문
    cursor cursor_name is
    select_statement;

 

명시적 커서 사용 철차

1) 커서 만들기
    declare 절에 커서를 생성(select 구문)
2) 커서 열기
    Open 커서이름;
3) 1행씩 가져 오기 : Fetch
    into 절 반드시 사용할 것 (데이터가 없을때까지 fetch)
4) 커서 닫기
    close 커서이름;

 

 예제)

declare
    cursor emp_cursor is
    select
        empno,
        ename
    from
        emp
    where
        deptno = 30;
       
    v_empno emp.empno%type;
    v_ename emp.ename%type;
    begin
        open emp_cursor; -- 커서 열기
  
        /*
            fetch 커서 내에서 1건씩 데이터 꺼내기
            into 절을 사용, select ... into 절과 유사하다.
        */    
       
        fetch emp_cursor into v_empno,v_ename;
        dbms_output.put_line('v_empno=>'||v_empno||'----'||'v_ename=>'||v_ename);
       
        fetch emp_cursor into v_empno,v_ename;
        dbms_output.put_line('v_empno=>'||v_empno||'----'||'v_ename=>'||v_ename);
       
        close emp_cursor;
    end;
    /

 

암묵적 으로 편하게 사용하기. - cursor for loops

 

특징 : open , fetch, exit , close 가 암묵적으로 진행.

 

기본구문

for record_name in cursor_name loop
   
end loop;

 

개발은 해본사람은 알겠지만 위 구문은 배열을 일일이 for문을 작성해서 원하는데이터를 가져오는 번거로움을 최소화

하기위해서 생긴 for in 또는 foreach 와 같은 형태다.

 

예제)

declare
    cursor emp_cursor is
    select
        deptno,
        ename,
        sal
    from
        emp;
   
begin
    for rs in emp_cursor loop


        if rs.deptno = 30 then
            dbms_output.put_line('===>'||rs.ename||' -- '||rs.sal);
        end if;
   
    end loop;
end;
/

결과)

===>ALLEN -- 1600
===>WARD -- 1250
===>MARTIN -- 1250
===>BLAKE -- 2850
===>TURNER -- 1500
===>JAMES -- 950


'Oracle > 오라클 양성반 15기' 카테고리의 다른 글

SYSOPER  (0) 2010.09.28
dbca. script, template 이것저것  (0) 2010.09.12
pl/sql exception  (0) 2010.09.12
merge into  (0) 2010.09.12
for update  (0) 2010.09.12