상세 컨텐츠

본문 제목

[오라클 교재] 제22장 BUILD PL/SQL SUBPROGRAMS

프로그래밍/DB

by 라제폰 2008. 12. 26. 21:12

본문

1. SUBPROGRAM

PL/SQL을 지원하는 어떤 툴이나 언어에서도 SUBPROGRAM(프로시저와 함수)을 실행할 수 있다. PL/SQL내부에서 식의 일부로서 함수를 실행할 수 있다. EXECUTE는 명령 다음에 입력되는 Stored Procedure를 실행한다.

 

1.1 SUBPROGRAM의 개요

PL/SQL 프로시저와 함수는 3GL의 프로시저 및 함수와 매우 비슷하게 동작된다. 모듈화를 통해 관리가 용이하고 적절히 논리적 단위로 나누어진 프로그래밍을 할 수 있다. , 잘 정의된 논리적인 단위로 코드를 분할할 수 있다. PL/SQL에서 이들 단위를 단위 프로그램 또는 SUBPROGRAM이라 부른다. PL/SQL에는 프로시저와 함수라는 두 가지 유형의 SUBPROGRAM이 있다. SUBPROGRAM은 컴파일된 상태로 데이터베이스에 저장되어 있어 Performance가 향상된다.

 

1.2 SUBPROGRAM 작성 단계

1.2.1 구문 작성

TEXT 편집기를 이용하여 SCRIPT FILE CREATE PROCEDURE CREATE FUNCTION문을 작성한다.

SQL> ed emp_up

 

        CREATE OR REPLACE PROCEDURE emp_sal_update(

               p_empno IN emp.empno%TYPE, p_sal IN emp.sal%TYPE)

        IS

        BEGIN

               UPDATE emp

                       SET sal = p_sal

                       WHERE empno = p_empno;

               IF SQL%NOTFOUND THEN

                       DBMS_OUTPUT.PUT_LINE(TO_CHAR(p_empno) ||

                              '는 없는 사원번호입니다.');

               ELSE

                       DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQL%ROWCOUNT) ||

                              '명의 자료를 수정하였습니다.');

               END IF;

        END emp_sal_update;

        /

 

 

1.2.2 코드 컴파일

SCRIPT FILE을 실행 시켜 컴파일하여 컴파일된 코드를 데이터베이스에 저장한다.

SQL> @emp_up

 

Procedure created.

1.2.3 에러 수정

코드 컴파일시 에러가 발생하면 에러를 확인하고 수정하여 코드를 다시 컴파일한다.

SQL> @emp_up

 

Warning: Procedure created with compilation errors.

 

SQL> ed emp_up

                -- emp_up를 수정한 후 저장하고 종료한다.

SQL> @emp_up

 

Procedure created.

 

1.2.4 실행

SQL*Plus에서 EXECUTE명령으로 SUBPROGRAM을 실행한다.

SQL> EXECUTE emp_sal_update(7788,3500)

 

PL/SQL procedure successfully completed.

 

SQL> SELECT empno,ename,job,sal

  2  FROM emp

  3  WHERE empno = 7788;

 

    EMPNO ENAME      JOB             SAL

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

     7788 SCOTT      ANALYST        3500

 

♣ 참고

변경된 내용을 확인하기 위해 SELECT문을 사용할 수 있다.

 

1.3 PROCEDURE 생성

나중에 실행할 일련의 동작을 저장하기 위해 PL/SQL프로시저를 작성한다. 프로시저는 실행할 때 사용하는 Parameter가 없거나 여러 개를 가질 수도 있다. 프로시저에서는 DECLARE절이 생략되고 IS BEGIN사이에 필요한 변수를 선언하여 사용한다

 

1.3.1 Syntax

CREATE  [OR  REPLACE]  PROCEDURE  procedure_name

        [(argument1  [mode1]  datatype [{:= | DEFAULT} expression]

        [,argument2  [mode2]  datatype [{:= | DEFAULT} expression], . . .])]

{IS | AS}

BEGIN

        pl/sql_block;

END;

OR  REPLACE  procedure_name이 존재할 경우 PROCEDURE의 내용을 지우고 다시 생성

procedure_name       PROCEDURE

argument     매개변수의 이름

mode         3가지가 있다

             IN : 입력 매개변수로 상용

             OUT : 출력 매개변수로 사용

             IN OUT : 입력, 출력 매개변수로 상용

pl/sql_block PROCEDURE를 구성하는 코드를 구성하는 PL/SQL의 블록

 

Guidelines

1)       SQL*Plus에서 프로시저를 작성할 때 CREATE OR REPLACE를 사용하시오.

2)       어떠한 Parameter라도 사용 가능하다.

3)       IS PL/SQL블록을 시작하시오.

4)       Local변수 선언은 IS BEGIN사이에 선언 하시오.

 

1.3.2 PROCEDURE 실행

PL/SQL을 지원하는 어떤 툴이나 언어에서도 프로시저를 실행할 수 있다. SQL*Plus에서 프로시저 호출은 Stored Procedure를 참조하는 PL/SQL 문을 실행하기 위해 EXECUTE 명령을 사용할 수 있다. EXECUTE는 명령 다음에 입력되는 Stored Procedure를 실행한다.

 

) Syntax

procedure_name[(argument1[,argument2, . . . .])]

 

) SQL*Plus에서 프로시저 실행

EXECUTE는 명령 다음에 입력되는 Stored Procedure를 실행한다.

SQL> EXECUTE emp_sal_update(7902,4000)

 

PL/SQL procedure successfully completed.

 

 

 

 

 

 

 

 

 

문제1) EMP 테이블에 새로운 사원의 정보를 이름,업무,매니저,급여를 입력받아 등록하는 프로시저를 생성하여라. 단 부서 번호는 매니저의 부서 번호와 동일하게 하고 보너스는 SALESMAN 0을 그 외는 NULL을 입력하여라.

CREATE OR REPLACE PROCEDURE emp_input(

        v_name  IN      emp.ename %TYPE,

        v_job   IN      emp.job %TYPE,

        v_mgr   IN      emp.mgr %TYPE,

        v_sal   IN      emp.sal %TYPE)

IS

        v_comm         emp.comm%TYPE;

        v_deptno               emp.deptno%TYPE;

        manager_error  EXCEPTION;

BEGIN

        IF UPPER(v_job) NOT IN ('PRESIDENT','MANAGER','ANALYST',

                              'SALESMAN','CLERK') THEN

               RAISE manager_error;

        ELSIF UPPER(v_job) = 'SALESMAN' THEN

               v_comm := 0;

        ELSE

               v_comm := NULL;

        END IF;

        SELECT deptno

               INTO v_deptno

               FROM emp

               WHERE empno = v_mgr;

        INSERT INTO emp

               VALUES (empno_sequence.NEXTVAL,v_name,UPPER(v_job),

                       v_mgr,SYSDATE,v_sal,v_comm,v_deptno);

EXCEPTION

        WHEN manager_error THEN

               DBMS_OUTPUT.PUT_LINE('담당 업무가 잘못 입력되었습니다.');

        WHEN NO_DATA_FOUND THEN

               DBMS_OUTPUT.PUT_LINE('입력한 MANAGER는 없습니다.');

        WHEN OTHERS THEN

               DBMS_OUTPUT.PUT_LINE('기타 에러입니다.');

END;

/

SQL> SET SERVEROUTPUT ON

SQL> EXECUTE emp_input('YOONJB','MANAGER',7788,2500)

 

 

 

 

 

문제2) 이름을 입력받아 그 사원의 정보 중 부서명과 급여를 검색하는 프로시저를 생성하여라.

CREATE OR REPLACE PROCEDURE dname_sal_disp(

        v_ename IN      emp.ename%TYPE,

        v_dname OUT     dept.dname%TYPE,

        v_sal   OUT     emp.sal%TYPE)

IS

        v_deptno       emp.deptno%TYPE;

BEGIN

        SELECT sal,deptno

               INTO v_sal,v_deptno

               FROM emp

               WHERE ename = UPPER(v_ename);

        SELECT dname

               INTO v_dname

               FROM dept

               WHERE deptno = v_deptno;

EXCEPTION

        WHEN NO_DATA_FOUND THEN

               DBMS_OUTPUT.PUT_LINE('입력한 MANAGER는 없습니다.');

        WHEN TOO_MANY_ROWS THEN

               DBMS_OUTPUT.PUT_LINE('자료가 2건 이상입니다.');

        WHEN OTHERS THEN

               DBMS_OUTPUT.PUT_LINE('기타 에러입니다.');

END;

/

SQL> VAR g_dname VARCHAR2(14)

SQL> VAR g_sal NUMBER

SQL> EXECUTE dname_sal_disp('SCOTT',:g_dname,:g_sal);

PL/SQL procedure successfully completed.

SQL> PRINT g_dname

G_DNAME

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

ACCOUNTING

SQL> PRINT g_sal

    G_SAL

---------

     3000

 

 

 

 

 

 

 

문제3) 이름을 입력받아 그 사원의 정보 중 부서명과 급여를 검색하는 프로시저를 생성하여라.

CREATE OR REPLACE PROCEDURE tel(

        v_tel   IN OUT  VARCHAR2)

IS

BEGIN

        v_tel := SUBSTR(v_tel,1,3) || '-' || SUBSTR(v_tel,4);

        DBMS_OUTPUT.PUT_LINE('전화번호 : ' || v_tel);

END tel;

/

SQL> SET SERVEROUTPUT ON

SQL> VAR g_tel VARCHAR2(20)

SQL> BEGIN

  2  :g_tel := 1234567;

  3  END;

  4  /

PL/SQL procedure successfully completed.

SQL> EXECUTE tel(:g_tel)

전화번호 : 123-4567

PL/SQL procedure successfully completed.

SQL> PRINT g_tel

G_TEL

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

123-4567

 

1.4 FUNCTION 생성

실행 환경에 반드시 하나의 값을 Return하기 위해 PL/SQL 함수를 사용한다. 함수 선언에서 Datatype이 있는 RETURN 절을 추가하고 PL/SQL 블록에 적어도 한 개의 이상의 RETURN 문을 포함한다. PARAMETER에서 사용하는 IN,OUT,IN OUT PROCEDURE에서 사용한 것과 동일하게 사용 가능하나 대부분 IN을 사용한다.

 

1.4.1 Syntax

CREATE  [OR  REPLACE]  FUNCTION  function_name

        [(argument1  [mode1]  datatype [{:= | DEFAULT} expression]

        [,argument2  [mode2]  datatype [{:= | DEFAULT} expression], . . .])]

RETURN  data_type

{IS | AS}

BEGIN

        pl/sql_block;

END;

OR  REPLACE  function_name이 존재할 경우 FUNCTION의 내용을 지우고 다시 생성

function_name Function의 이름은 표준 Oracle 명명법에 따른 함수이름

argument     매개변수의 이름

mode         3가지가 있다

             IN : 입력 매개변수로 상용

             OUT : 출력 매개변수로 사용

             IN OUT : 입력, 출력 매개변수로 상용

data_type    반환되는 값의 datatype

pl/sql_block FUNCTION를 구성하는 코드를 구성하는 PL/SQL의 블록

 

1.4.2  RETURN

1)       PL/SQL 블록에는 RETURN문이 있어야 한다.

2)       함수는 RETURN 절에 지정된 것과 동일한 datatype으로 RETURN 값을 설정해야 한다.

3)       다중 RETURN 문은 사용할 수 있지만 한 번의 호출로는 한 개의 RETURN 문만 실행된다.

4)       일반적으로 다중 RETURN 문은 IF 문에서 사용한다.

 

1.4.3  FUNCTION 실행

PL/SQL을 지원하는 어떤 툴이나 언어에서도 함수를 실행할 수 있고 PL/SQL내부에서 식의 일부로서 함수를 실행할 수 있다. SQL*Plus에서 FUNCTION 호출은 Stored Function를 참조하는 PL/SQL 문을 실행하기 위해 EXECUTE 명령을 사용할 수 있다. EXECUTE는 명령 다음에 입력되는 Stored Function를 실행한다.

 

) Syntax

output_variable := function_name[(argument1[,argument2, . . . . .])]

 

) SQL*Plus에서 함수 실행

SQL> EXECUTE :g_deptno := ename_deptno('ALLEN')

 

PL/SQL procedure successfully completed.

 

문제4) EMP 테이블에서 이름으로 부서 번호를 검색하는 함수를 작성하여라.

CREATE OR REPLACE FUNCTION ename_deptno(

        v_ename IN      emp.ename%TYPE)

RETURN NUMBER

IS

        v_deptno       emp.deptno%TYPE;

BEGIN

        SELECT deptno

               INTO v_deptno

               FROM emp

               WHERE ename = UPPER(v_ename);

        DBMS_OUTPUT.PUT_LINE('부서번호 : ' || TO_CHAR(v_deptno));

        RETURN v_deptno;

EXCEPTION

        WHEN NO_DATA_FOUND THEN

               DBMS_OUTPUT.PUT_LINE('입력한 MANAGER는 없습니다.');

        WHEN TOO_MANY_ROWS THEN

               DBMS_OUTPUT.PUT_LINE('자료가 2건 이상입니다.');

        WHEN OTHERS THEN

               DBMS_OUTPUT.PUT_LINE('기타 에러입니다.');

END;

/

SQL> SET SERVEROUTPUT ON

SQL> VAR g_deptno NUMBER

SQL> EXECUTE :g_deptno := ename_deptno('SCOTT')

부서번호 : 10

 

PL/SQL procedure successfully completed.

 

SQL> PRINT g_deptno

 

 G_DEPTNO

---------

       10

 

문제5) EMP 테이블에서 이름을 입력 받아 부서번호,부서명,급여를 검색하는 FUNCTION을 작성하여라. 단 부서번호를 RETURN에 사용하여라.

CREATE OR REPLACE FUNCTION emp_disp(

        v_ename IN      emp.ename%TYPE,

        v_dname OUT     dept.dname%TYPE,

        v_sal   OUT     emp.sal%TYPE)

RETURN NUMBER

IS

        v_deptno       emp.deptno%TYPE;

        v_dname_temp   dept.dname%TYPE;

        v_sal_temp     emp.sal%TYPE;

BEGIN

        SELECT sal,deptno

               INTO v_sal_temp,v_deptno

               FROM emp

               WHERE ename = UPPER(v_ename);

        SELECT dname

               INTO v_dname_temp

               FROM dept

               WHERE deptno = v_deptno;

        v_dname := v_dname_temp;

        v_sal := v_sal_temp;

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

        DBMS_OUTPUT.PUT_LINE('부서번호 : ' || TO_CHAR(v_deptno));

        DBMS_OUTPUT.PUT_LINE('부 서 명 : ' || v_dname_temp);

        DBMS_OUTPUT.PUT_LINE('    : ' || TO_CHAR(v_sal_temp,'$999,999'));

        RETURN v_deptno;

EXCEPTION

        WHEN NO_DATA_FOUND THEN

               DBMS_OUTPUT.PUT_LINE('입력한 MANAGER는 없습니다.');

        WHEN TOO_MANY_ROWS THEN

               DBMS_OUTPUT.PUT_LINE('자료가 2건 이상입니다.');

        WHEN OTHERS THEN

               DBMS_OUTPUT.PUT_LINE('기타 에러입니다.');

END;

/

SQL> SET SERVEROUTPUT ON

SQL> VAR g_deptno NUMBER

SQL> VAR g_dname VARCHAR2(20)

SQL> VAR g_sal NUMBER

SQL> EXECUTE :g_deptno := emp_disp('scott',:g_dname,:g_sal)

    : scott

부서번호 : 10

부 서 명 : ACCOUNTING

    :    $3,000

PL/SQL procedure successfully completed.

SQL> PRINT g_deptno

 G_DEPTNO

---------

       10

SQL> PRINT g_dname

G_DNAME

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

ACCOUNTING

SQL> PRINT g_sal

    G_SAL

---------

     3000

 

1.5 함수와 프로시저 비교

프로시저

함수

PL/SQL 문으로서 실행

식의 일부로서 사용

RETURN Datatype이 없음

RETURN Datatype이 필수

값을 Return할 수 있음

값을 Return하는 것이 필수

 

♣ 참고

1)       프로시저는 parameter리스트를 가질 수 있지만 값 반환이 필수적 이지는 않다.

2)       함수는 다음과 같은 두 가지 점에서 프로시저와 다르다.

       (expression)의 일부로서 함수를 사용한다.

       함수는 값을 return하는 것이 필수적이다.

1.6 TRIGGER

특정 테이블에 DML(INSERT,UPDATE,DELETE)문장이 수행되었을 때 데이터베이스에서 자동적으로 PL/SQL 블록을 수행 시키기 위해서 데이터베이스 TRIGGER를 사용한다. TRIGGER는 트리거링 이벤트가 일어날 때마다 암시적으로 실행된다. 트리거링 이벤트에는 데이터베이스 테이블에서 INSERT,UPDATE,DELETE 오퍼레이션이다.

 

1.6.1 TRIGGER가 사용되는 경우

1)       테이블 생성시 CONSTRAINT로 선언 제한이 불가능하고 복잡한 무결성 제한을 유지

2)       DML문장을 사용한 사람,변경한 내용,시간 등을 기록함으로써 정보를 AUDIT하기

3)       테이블을 변경할 때 일어나야 할 동작을 다른 테이블 또는 다른 프로그램들에게 자동적으로 신호하기

 

1.6.2 TRIGGER에 대한 제한

1)       TRIGGER는 트랜잭션 제어 문(COMMIT,ROLLBACK,SAVEPOINT)장을 사용하지 못한다.

2)       TRIGGER 주요부에 의해 호출되는 프로시저나 함수는 트랜잭션 제어 문장을 사용하지 못한다.

3)       TRIGGER 주요부는 LONG또는 LONG RAW변수를 선언할 수 없다.

4)       TRIGGER 주요부가 액세스하게 될 테이블에 대한 제한이 있다.

 

1.6.3 TRIGGER생성

CREATE TRIGGER문장에 의해 TRIGGER를 생성할 수 있다.

 

) Syntax

CREATE  [OR  REPLACE]  TRIGGER  trigger_name

        {BEFORE | AFTER}  triggering_event [OF  column1, . . .] ON table_name

        [FOR  EACH  ROW  [WHEN  trigger_condition]

trigger_body;

trigger_name         TRIGGER의 식별자

BEFORE | AFTER               DML문장이 실행되기 전에 TRIGGER를 실행할 것인지 실행된

                     후에 TRIGGER를 실행할 것인지를 정의

triggering_event     TRIGGER를 실행하는 DML(INSERT,UPDATE,DELETE)문을 기술한다.

OF column            TRIGGER가 실행되는 테이블에서 COLUMN명을 기술한다.

table_name           TRIGGER가 실행되는 테이블 이름

FOR EACH ROW         이 옵션을 사용하면 행 레벨 트리거가 되어 triggering문장

                     에 의해 영향받은 행에 대해 각각 한번씩 실행하고 사용하지

                     않으면 문장 레벨 트리거가 되어 DML문장 당 한번만 실행된다.

 

) TRIGGER에서 OLD NEW

행 레벨 TRIGGER에서만 사용할 수 있는 예약어로 트리거 내에서 현재 처리되고 있는 행을 액세스할 수 있다. 즉 두개의 의사 레코드를 통하여 이 작업을 수행할 수 있다. :OLD INSERT문에 의해 정의되지 않고 :NEW DELETE에 대해 정의되지 않는다. 그러나 UPDATE :OLD :NEW를 모두 정의한다. 아래의 표는 OLD NEW값을 정의한 표이다.

 

문장

:OLD

:NEW

INSERT

모든 필드는 NULL로 정의

문장이 완전할 때 삽입된 새로운 값

UPDATE

갱신하기 전의 원래 값

문장이 완전할 때 갱신된 새로운 값

DELETE

행이 삭제되기 전의 원래 값

모든 필드는 NULL이다.

 

) TRIGGER 술어 사용하기

트리거 내에서 오퍼레이션이 무엇인지를 결정하기 위해 사용할 수 있는 3가지 BOOLEAN함수가 있다.

술 어

    

INSERTING

트리거링 문장이 INSERT이면 TRUE를 그렇지 않으면 FALSE RETURN

UPDATING

트리거링 문장이 UPDATE이면 TRUE를 그렇지 않으면 FALSE RETURN

DELETING

트리거링 문장이 DELETE이면 TRUE를 그렇지 않으면 FALSE RETURN

 

) TRIGGER 삭제와 억제하기

DROP TRIGGER명령어로 트리거를 삭제할 수 있고 TRIGGER를 잠시 disable할 수 있다.

DROP  TRIGGER  trigger_name;

ALTER  TRIGGER  trigger_name  {DISABLE | ENABLE};

 

) TRIGGER DATA DICTIONARY

TRIGGER가 생성될 때 소스 코드는 데이터 사전 VIEW user_triggers에 저장된다. VIEW TRIGGER_BODY, WHERE, 트리거링 테이블, TRIGGER 타입을 포함 한다.

SQL> SELECT trigger_type,table_name,triggering_event

  2  FROM user_triggers;

 

TRIGGER_TYPE     TABLE_NAME                     TRIGGERING_EVENT

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

AFTER STATEMENT  EMP                            INSERT OR UPDATE OR DELETE

BEFORE STATEMENT EMP                            INSERT OR UPDATE OR DELETE

BEFORE EACH ROW  EMP                            UPDATE

 

 

문제6) EMP 테이블에서 급여를 수정시 현재의 값보다 적게 수정할 수 없으며 현재의 값보다 10% 이상 높게 수정할 수 없다. 이러한 조건을 만족하는 트리거를 작성하여라.

CREATE OR REPLACE TRIGGER emp_sal_chk

BEFORE UPDATE OF sal ON emp

FOR EACH ROW WHEN (NEW.sal < OLD.sal

               OR NEW.sal > OLD.sal * 1.1)

BEGIN

        raise_application_error(-20502,

           'May not decrease salary. Increase must be < 10%');

END;

/

SQL> @emp_sal

 

Trigger created.

SQL> update emp

  2  set sal = 6000;

set sal = 6000

             *

ERROR at line 2:

ORA-20502: May not decrease salary. Increase must be < 10%

ORA-06512: at "SCOTT.EMP_SAL_CHK", line 2

ORA-04088: error during execution of trigger 'SCOTT.EMP_SAL_CHK'

 

문제7) EMP 테이블을 사용할 수 있는 시간은 월요일부터 금요일까지 09시부터 18시까지만 사용할 수 있도록 하는 트리거를 작성하여라.

CREATE OR REPLACE TRIGGER emp_resource

        BEFORE insert OR update OR delete ON emp

BEGIN

        IF TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')

               OR TO_NUMBER(TO_CHAR(SYSDATE,'HH24'))

                       NOT BETWEEN 9 AND 18 THEN

               raise_application_error(-20502,

                  '작업할 수 없는 시간 입니다.');

        END IF;

END;

/

SQL> @tr1

 

Trigger created.

SQL> select to_char(sysdate,'hh24') from dual;

TO_CHAR(SYSDATE,'HH24')

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

19

SQL> update emp

  2  set deptno = 10;

update emp

       *

ERROR at line 1:

ORA-20502: 작업할 수 없는 시간 입니다.

ORA-06512: at "SCOTT.EMP_RESOURCE", line 5

ORA-04088: error during execution of trigger 'SCOTT.EMP_RESOURCE'

 

문제8) EMP 테이블에 INSERT,UPDATE,DELETE문장이 하루에 몇 건 발생하는지 조사하려고 한다. 조사 내용은 EMP_AUDIT에 사용자 이름, 작업 구분,작업 시간을 저장하는 트리거를 작성하여라.

CREATE SEQUENCE emp_audit_tr

        INCREMENT BY 1

        START WITH 1

        MAXVALUE 999999

        MINVALUE 1

        NOCYCLE

        NOCACHE;

CREATE TABLE emp_audit(

        e_id    NUMBER(6)

               CONSTRAINT emp_audit_pk PRIMARY KEY,

        e_name  VARCHAR2(30),

        e_gubun VARCHAR2(10),

        e_date  DATE);

 

CREATE OR REPLACE TRIGGER emp_audit_tr

        AFTER insert OR update OR delete ON emp

BEGIN

        IF INSERTING THEN

               INSERT INTO emp_audit

               VALUES(emp_audit_tr.NEXTVAL,USER,'inserting',SYSDATE);

        ELSIF UPDATING THEN

               INSERT INTO emp_audit

               VALUES(emp_audit_tr.NEXTVAL,USER,'updating',SYSDATE);

        ELSIF DELETING THEN

               INSERT INTO emp_audit

               VALUES(emp_audit_tr.NEXTVAL,USER,'deleting',SYSDATE);

        END IF;

END;

/

SQL> UPDATE emp

  2  SET deptno = 20

  3  WHERE deptno = 10;

2 row updated.

SQL> SELECT * FROM emp_audit;

     E_ID E_NAME                         E_GUBUN    E_DATE

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

        1 SCOTT                          updating   23-FEB-99

 

문제9) EMP 테이블에 INSERT,UPDATE,DELETE문장이 하루에 몇 건의 ROW가 발생되는지 조사하려고 한다. 조사 내용은 EMP_AUDIT_ROW에 사용자 이름, 작업 구분,작업 시간,사원번호,이전의 급여, 갱신된 급여을 저장하는 트리거를 작성하여라.

DROP SEQUENCE emp_row_seq;

CREATE SEQUENCE emp_row_seq

        INCREMENT BY 1

        START WITH 1

        MAXVALUE 999999

        MINVALUE 1

        NOCYCLE

        NOCACHE;

DROP TABLE emp_row_tab;

CREATE TABLE emp_row_tab(

        e_id           NUMBER(6)

               CONSTRAINT emp_row_pk PRIMARY KEY,

        e_name         VARCHAR2(30),

        e_gubun        VARCHAR2(10),

        e_date         DATE);

CREATE OR REPLACE TRIGGER emp_row_aud

        AFTER insert OR update OR delete ON emp

        FOR EACH ROW

BEGIN

        IF INSERTING THEN

               INSERT INTO emp_row_tab

                       VALUES(emp_row_seq.NEXTVAL,USER,'inserting',SYSDATE);

        ELSIF UPDATING THEN

               INSERT INTO emp_row_tab

                       VALUES(emp_row_seq.NEXTVAL,USER,'updating',SYSDATE);

        ELSIF DELETING THEN

               INSERT INTO emp_row_tab

                       VALUES(emp_row_seq.NEXTVAL,USER,'deleting',SYSDATE);

        END IF;

END;

/

SQL> UPDATE emp

  2  SET deptno = 40

  3  WHERE deptno = 10;

 

3 rows updated.

 

SQL> SELECT * FROM emp_row_tab;

 

     E_ID E_NAME                         E_GUBUN    E_DATE

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

        1 SCOTT                          updating   23-FEB-99

        2 SCOTT                          updating   23-FEB-99

        3 SCOTT                          updating   23-FEB-99

 


◈ 연 습 문 제 ◈

 

1. EMP TABLE에 이름,사번,급여,부서번호를 전달받아 등록하는 PROCEDURE를 작성하여라.

 

 

2. 사원번호를 입력받아 급여를 수정하는 PROCEDURE를 작성하여라.

 

 

3. 최고의 월급을 받는 사원의 사번을 구하여 출력하는 PROCEDURE를 작성하여라.

 

 

4. 이름을 입력받아 부서명을 구하여 출력하는 PROCEDURE를 작성하여라.

 

 

5. 부서번호를 입력받아 그 부서의 최고 급여를 구하여 출력하는 FUNCTION을 작성하여라.

 

 

6. PROCEDURE FUNCTION의 차이점을 설명하여라.

 

 

7. TRIGGER ?

 

 

8. EMP_SAL_TOT(부서번호,급여의 합) TABLE을 생성하여라.

SQL> CREATE TABLE emp_sal_tot as

  2  SELECT deptno,SUM(sal) sal_tot

  3  FROM emp

  4  GROUP BY deptno;

 

Table created.

 

9. EMP_SAL_TOT TABLE의 내용은 EMP TABLE을 변경하면 EMP_SAL_TOT TABLE의 내용도 자동적으로 변경되어야 한다. 이를 반영한 TRIGGER를 작성하여라.

 


관련글 더보기