PL/SQL로 만든 프로그램을 주기적으로 또는 필요할 때마다 여러 번 사용할 목적으로 이름을 지정하여 오라클에 저장해 두는 PL/SQL 프로그램을 저장 서브프로그램(stored subprogram)이라고 합니다.
2) 익명 블록과 달리 저장 서브프로그램은 오라클에 저장하여 공유할 수 있으므로 메모리,성능,재사용성 등 여러 면에서 장점
3) 종류
1) 문법
CREATE [OR REPLACE] PROCEDURE 프로시저 이름
IS | AS
선언부 - 변수 정의, 커서 정의
BEGIN
실행부
EXCEPTION -
예외 처리부
END [프로시저 이름];
2) 프로시저 생성하기
CREATE OR REPLACE PROCEDURE PRO_NOPARAM
IS
V_DEPTNO DEPT.DEPTNO%TYPE;
V_DNAME DEPT.DNAME%TYPE;
BEGIN
SELECT DEPTNO, DNAME INTO V_DEPTNO, V_DNAME
--DEPTNO, DNAME를 조회해 후 복사해서 INTO뒤 변수에 넣기
FROM DEPT WHERE DEPTNO = 30;
DBMS_OUTPUT.PUT_LINE('DEPTNO: '||V_DEPTNO);
DBMS_OUTPUT.PUT_LINE('DNAME: '|| V_DNAME);
END PRO_NOPARAM;

3) 프로시저 실행하기
CALL 프로시저명(값, ...);

4) PL/SQL 블록에서 프로시저 실행하기
BEGIN
프로시저명(값,...);
END;

BEGIN
PRO_NOPARAM;
--매개변수가 없는 경우엔 이름 형태도 가능
END;
5) 프로시저 내용 확인하기
6) 프로시저 삭제하기
DROP PROCEDURE 프로시저명;
1) 문법
CREATE [OR REPLACE(1)] PROCEDURE 프로시저 이름
[(파라미터 이름1 [modes] 자료형 [ := | DEFAULT 기본값],
파라미터 이름2 [modes] 자료형 [ := | DEFAULT 기본값],
...
파라미터 이름N [modes] 자료형 [ := | DEFAULT 기본값]
)]
IS | AS
선언부
BEGIN
실행부
EXCEPTION
예외 처리부
END [프로시저 이름];
2) 파라미터 모드
3) IN 모드 파라미터 - 내부에서 사용할 목적
CREATE OR REPLACE PROCEDURE PRO_PARAM_IN(
P_DEPTNO IN NUMBER, -- 내부에서 쓰이는 변수
P_JOB IN VARCHAR2 -- IN생략 가능
--두개의 매개변수 존재
)
IS
BEGIN
FOR d IN (SELECT * FROM EMP
WHERE DEPTNO = P_DEPTNO AND JOB = P_JOB)
LOOP
DBMS_OUTPUT.PUT_LINE('EMPNO: '|| d.EMPNO);
DBMS_OUTPUT.PUT_LINE('ENAME: '|| d.ENAME);
DBMS_OUTPUT.PUT_LINE('JOB: '|| d.JOB);
DBMS_OUTPUT.PUT_LINE('------------------');
END LOOP;
END PRO_PARAM_IN; --프로시저명 꼭 같이 입력해줘야함
SELECT * FROM USER_ERRORS;
CALL PRO_PARAM_IN(20,'CLERK');
4) OUT 모드 파라미터 - 외부로 내보냄
CREATE OR REPLACE PROCEDURE PRO_PARAM_OUT(
P_DEPTNO EMP.DEPTNO%TYPE,
O_SUM OUT NUMBER, -- OUT생략 불가
O_AVG OUT NUMBER -- 내부로 내보낼 변수
)
IS
BEGIN
SELECT SUM(SAL), ROUND(AVG(SAL),2) INTO O_SUM, O_AVG
FROM EMP WHERE DEPTNO = P_DEPTNO;
END PRO_PARAM_OUT; --프로시저명 꼭 같이 입력해줘야함

5) IN OUT 모드 파라미터

1) SHOW ERRORS /sqlplus
2) USER_ERRORS: 사전 테이블

CREATE [OR REPLACE] FUNCTION 함수 이름
[(
파라미터 이름1 [IN] 자료형1, - (1)
파라미터 이름2 [IN] 자료형2,
...
파라미터 이름N [IN] 자료형N
)]
RETURN 자료형 - (2)
IS | AS
선언부
BEGIN
실행부
RETURN (반환 값); - (3)
EXCEPTION
예외 처리부
END [함수 이름];
CREATE OR REPLACE FUNCTION FUNC_AFTERTAX(
P_SAL NUMBER
)
RETURN NUMBER
IS --선언부
TAX NUMBER := 0.05;
SAL NUMBER; --변수 선언
BEGIN --실행부
SAL := ROUND(P_SAL - P_SAL * TAX);
RETURN SAL;
END FUNC_AFTERTAX;
1) PL/SQL로 함수 실행하기

2) SQL문에서 함수 실행하기


DROP FUNCTION 함수명1) 패키지 명세
패키지 명세는 패키지에 포함할 변수, 상수, 예외, 커서 그리고 PL/SQL 서브프로그램을 선언하는 용도로 작성합니다.
패키지 명세에 선언한 여러 객체는 패키지 내부뿐만 아니라 외부에서도 참조할 수 있습니다.
문법
CREATE [OR REPLACE] PACKAGE 패키지 이름
IS | AS
서브프로그램을 포함한 다양한 객체 선언
END [패키지 이름];
CREATE OR REPLACE PACKAGE PKG_EMP
IS
FUNCTION FUNC_AFTERTAX(P_SAL NUMBER) RETURN NUMBER;
PROCEDURE PRO_SEARCH_EMP(
P_DEPTNO EMP.DEPTNO%TYPE, P_JOB EMP.JOB%TYPE);
END PKG_EMP;

2) 패키지 본문
CREATE [OR REPLACE] PACKAGE BODY 패키지 이름
IS | AS
패키지 명세에서 선언한 서브프로그램을 포함한 여러 객체를 정의
경에우 따라 패키지 명세에 존재하지 않는 객체 및 서브프로그램도 정의 가능
END [패키지 이름];

CREATE OR REPLACE PACKAGE BODY PKG_EMP
IS
FUNCTION FUNC_AFTERTAX(P_SAL NUMBER) RETURN NUMBER
IS
TAX NUMBER := 0.05;
SAL NUMBER;
BEGIN
SAL := ROUND(P_SAL - P_SAL * TAX);
RETURN SAL;
END FUNC_AFTERTAX;
PROCEDURE PRO_SEARCH_EMP(
P_DEPTNO EMP.DEPTNO%TYPE,
P_JOB EMP.JOB%TYPE)
IS
BEGIN
FOR d IN(SELECT * FROM EMP
WHERE DEPTNO = P_DEPTNO AND JOB = P_JOB )
LOOP
DBMS_OUTPUT.PUT_LINE('EMPNO: '|| d.EMPNO);
DBMS_OUTPUT.PUT_LINE('ENAME: '|| d.ENAME);
DBMS_OUTPUT.PUT_LINE('JOB: '|| d.JOB);
DBMS_OUTPUT.PUT_LINE('-----------------');
END LOOP;
END PRO_SEARCH_EMP;
END PKG_EMP;
패키지 사용하기

패키지 삭제하기
DROP PACKAGE 패키지명; -> 패키지 명세 + 패키지
DROP PACKAGE BODY 패키지명; -> 패키지 본문만 삭제
트리거란?
1) 데이터베이스 안의 특정 상황이나 동작, 즉 이벤트가 발생할 경우에 자동으로 실행되는 기능을 정의하는 PL/SQL 서브프로그램
2) 트리거는 특정 작업 또는 이벤트 발생으로 다른 데이터 작업을 추가로 실행하기 때문에 무분별하게 사용하면 데이터베이스 성능을 떨어뜨리는 원인이 되므로 주의
DML 트리거
1) DML 트리거 형식
CREATE [OR REPLACE] TRIGGER 트리거 이름 - (1)
BEFORE | AFTER - (2)
INSERT | UPDATE | DELETE ON 테이블 이름 - (3)
REFERENCING OLD as old | NOW as new - (4)
FOR EACH ROW WHEN 조건식 - (5)
FOLLOWS 트리거 이름2, 트리거 이름3 ... - (6)
ENABLE | DISABLE - (7)
DECLARE
선언부
BEGIN
실행부
EXCEPTION
예외 처리부
END;
CREATE TABLE EMP_TRG AS SELECT * FROM EMP;
2) DML 실행 전에 수행할 트리거 생성하기

CREATE OR REPLACE TRIGGER TRG_EMP_NODML
BEFORE
INSERT OR UPDATE OR DELETE ON EMP_TRG
BEGIN
IF TO_CHAR(SYSDATE, 'DY') IN ('화', '수') THEN
IF INSERTING THEN
raise_application_error(-20000, '추가 불가');
ELSIF UPDATING THEN
raise_application_error(-20000, '수정 불가');
ELSIF DELETING THEN
raise_application_error(-20000, '삭제 불가');
ELSE
raise_application_error(-20000, '작업 불가');
END IF;
END IF;
END;
CREATE TABLE EMP_TRG_LOG (
DML_TYPE VARCHAR2(20),
EMPNO NUMBER(4),
ENAME VARCHAR2(20),
REGDT DATE DEFAULT SYSDATE
);
2) EMP_TRG_LOG 테이블에 EMP_TRG 테이블 데이터 변경 사항을 기록하는 트리거를 생성
:NEW - INSERT시 추가된 레코드 참조
:OLD - UPDATE, DELTENTE시 수정된 레코드 참조
CREATE OR REPLACE TRIGGER TRG_EMP_LOG
AFTER
INSERT OR UPDATE OR DELETE ON EMP_TRG
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO EMP_TRG_LOG (DML_TYPE, EMPNO, ENAME)
VALUES ('INSERT', :NEW.EMPNO, :NEW.ENAME);
ELSIF UPDATING THEN
INSERT INTO EMP_TRG_LOG (DML_TYPE, EMPNO, ENAME)
VALUES ('UPDATE', OLD.EMPNO, OLD.ENAME);
ELSIF DELETING THEN
INSERT INTO EMP_TRG_LOG (DML_TYPE, EMPNO, ENAME)
VALUES ('DELETING', OLD.EMPNO, OLD.ENAME);
END IF;
END;

ALTER TRIGGER 트리거 이름 ENABLE | DISABLE;
DROP TRIGGER 트리거명