티스토리 툴바


technology/web | script2010/03/14 00:39

1. Creating Stored Procedures

PROCEDURE / FUNCTION
: 차이점은 리턴값 여부??

    -. sqlplus 시작시마다 매번 "sql>define _editor=vi" 귀찮으니깐...
       login.sql 파일을 생성하여, 해당 구문을 넣으면 항상 실행된다.
       (set serveroutput on size unlimited 도 포함하면 좋지....)

    -. procedure 작성하고,

    -. 에러나면 "show error" 로 확인하고,

    -. execute "프로시져 이름" 실행

    -. 외부/프로그램에서 실행시에는 BEGIN my_proc; END; 식으로 호출하면 됨.

    * Procedure Parameter Mode
        -. IN : 외부에서 전달된 파라미터를 정의할 때
        -. OUT : 생성된 데이터를 외부로 전달 할때
        -. INOUT : IN OUT 변수를 하나로 ...

    -. 외부/프로그램에서 정의한 BIND변수를 실행할 때는 ":"을 사용한다.
        sqlplus 또는 Pro*C 에서 직접 지정한 변수는 BIND변수다.

    -- my_proc 프로시져 생성
    CREATE OR REPLACE PROCEDURE my_proc (p_id IN NUMBER, p_name OUT VARCHAR2)
    IS
        v_last_name employees.last_name%TYPE;
    BEGIN
        SELECT last_name INTO v_last_name
        FROM employees
        WHERE employee_id = p_id;
        p_name := v_last_name;
    END;
    /
    -- my_proc 프로시저의 OUT리턴값을 확인하기 위해서 다음을 실행
    DECLARE
        v_name VARCHAR2(30) := 'HELLO';
    BEGIN
        DBMS_OUTPUT.PUT_LINE(v_name);
        my_proc(102, v_name);
        DBMS_OUTPUT.PUT_LINE(v_name);
    END;
    /

    -- IN OUT 변수를 하나의 파라미터로 사용하기
    -- JOBS 테이블에서 job_id로 조회하고, job_title를 리턴받는다.
    CREATE OR REPLACE PROCEDURE pr_get_job (p_job IN OUT VARCHAR2)
    IS
    BEGIN
        SELECT job_title INTO p_job
        FROM jobs
        WHERE job_id = p_job;
    END;
    /
    -- pr_get_job 프로시저의 OUT리턴값을 확인하기 위해서 다음을 실행
    DECLARE
        v_job VARCHAR2(30) := 'SA_MAN';
    BEGIN
        DBMS_OUTPUT.PUT_LINE(v_job);
        my_proc(v_job);
        DBMS_OUTPUT.PUT_LINE(v_job);
    END;
    /

    * 삭제시에는
        DROP PROCEDURE procedure_name;


2. Creating Stored Functions

    * FUNCTION
        -. 리턴값이 할당되지 않는 곳에서는 사용 불가.
        -. SQL 안에서 함께 사용 가능하다.
        -. 프로시져와 비교해서 RETURN 절만이 추가된다.
    -- FUNCTION 사용하기
    -- join 으로 할 거 테스트하기 (이렇게 사용하지 말자) : 실제 Nested Loop Join을 발생시킨다..
    CREATE OR REPLACE FUNCTION fn_get_dept(p_dept IN NUMBER) RETURN VARCHAR2
    IS
        v_name VARCHAR2(50);>
    BEGIN
        SELECT department_name INTO v_name
        FROM departments
        WHERE department_id = p_dept;
        RETURN(v_name);
    END;
    /
    -- fn_get_dept FUNCTION 사용하기
    --column last_name format A20
    --column dname format A25
    SELECT employee_id, last_name, department_id,
                fn_get_dept(department_id) dname
    FROM employees;
    TIP) 위 처럼 하면, 모든 쿼리가 2번씩 실행되어, 성능에 지대한 영향을 끼친다.
          차라리 Sub Query 를 사용하자!
    (sub query는 같은 department_id 에 대해서는 쿼리가 한번만 실행된다!!)
    SELECT employee_id, last_name, department_id,
        ( SELECT department_name INTO v_name
        FROM departments
        WHERE department_id = A.department_id ) dname
    FROM employees A;
    * 삭제시에는
        DROP FUNCTION procedure_name;


    * Stored Function 제약사항!
    1) Parameter Mode : IN
    2) Parameter Data Type : Database Data Type
                                           -. Varchar2, Number : 정상
                                           -. Boolean, PLS-Integer : 사용불가
    3) Return Value Data Type  "2)" 동일
    4) DML 불가
    5) Commit , Rollback 불가
    6) 같은 테이블을 Fuction으로 만들고, 해당 Function을 같은 테이블로 처리시에는 에러!
         예) select ..., f(x) from emp  그리고  f(x) = select ... from emp 인 경우

    --> 실제 컴파일은 정상으로 처리되나, SQL과 함께 사용시에는 에러 발생됨!!!  (Runtime Error)


    * PROCEDURE 와 FUNCTION 차이
        -. standalone 형태로 사용할거면, procedure!!  (예 - 배치성 업무)
        -.


3. Creating Packages
    -. Oracle 패키지에서는 자주 사용 됨? (Forms, 기타 ... )
    -. OOP개념이 포함됨 (캡슐화)
    -. Specification + (Body) 로 구성됨.
        : spec에 정의한 내용들은 모두 public!  ex) public 변수, public procedure/function
          body에 정의한 내용들은 모두 private!  ex) private 변수, private proceduer/function
          body 내에서도 package 변수는 접근가능하나, local 변수라면 접근 불가.
          body없이 패키지만 사용하여, 상수 클래스와 같은 효과를 낼 수 있음.
    -. Anomymous, Procedure, Function 에서 사용 가능
        : Spec 접근 가능, Body 접근 불가
    -. 장단점.
        : 하나의 패키지로 묶으면, 한번의 IO만 발생하여, 성능이 좋다?
          대신 메모리 점유율 높아짐.
          여러개의 패키지로 안 묶고 단인 프로시져로 하면, 메모리는 낮지만 IO가 높아짐.
          그래서 관련있는 넘들만 패키지로 잘~ 묶을 것!

    * Spec
        -. public 성격, 외부 접근 가능
        -. Declaration : 선언

    * Body
        -. private 성격 : 외부 접근 불가
        -. Definition

    * 삭제
        DROP PACKAGE package_name;


    * BULK COLLECT
    * RETURNING ...
    * ...


10. Trigger
    -. DML/DDL Trigger 등이 있다.

    1) Statement Trigger
        : "For each Row" 사용하지 않음.
          DML 작업에 영향 받은 Row 수에 관계없이 1개 실행마다 1회만 fire

    2) Row Trigger
        : For each Row 키워드 사용
         영향받은 Row의 건수만큼 fire


    * Creating a DML Statement Trigger
    1) Trigger Timing : After, Before, (Instead of)
    2) Trigger Event : Insert, Update, Delete
    3) Trigger Table : ON <table명>
    4) Trigger Type : for each Row

    TIP) Trigger 를 이용해서 DML을 막을 수도 있다.
           -.  가령 업무 시간 이외에는 Insert 작업을 못 하도록 ...  (Page 10-11)
           -. 감사용도로써, DML을 일으키는 작업자와 시간, 예전 데이터 등을 기록 할 수도 있다. (Page 10-15)

저작자 표시
Posted by 승현아범