바닥코딩
패키지 본문
오라클 PL/SQL 에는 저장 패키지(Stored Package) 라는 개념이 존재합니다. 패키지라는 뜻과 같이 저장 패키지는 다양한 PL/SQL의 요소들을 묶어 하나의 프로그램 레벨로 제공할 수 있게 합니다. 패키지의 고유한 특성은 다음과 같습니다.
- 고유한 이름을 가진다
- 이름을 식별자로 사용하여 반복적으로 재사용이 가능합니다
- 패키지 내부는 타입, 상수, 변수, 커서 , 예외, 서브프로그램(함수,프로시저)등 대부분의 요소들을 포함할 수 있습니다
- 객체지향언어의 클래스와 유사한 기능을 가집니다.
- 정보 은닉의 기능이 강화됩니다
- 이해해기 쉽고 가독성이 뛰어납니다
- 신뢰성이 있으며 재사용성이 높은 프로그램을 만들 때 유용합니다.
패키지 명세
패키지는 명세와 본체로 나누어져 있습니다. 명세는 패키지 사용자에게 공개되는 타입, 상수,변수, 커서, 예외, 서브프로그램 등을 선언하는 오브젝트로, 패키지를 사용하기 위해서는 반드시 명시해야합니다. 예제를 통해 확인해 보겠습니다.
create or replace package pkg_emp
is
-- 공용 타입 선언
type emp_type is table of emp%rowtype;
-- 공용 상수 선언
c_deptno_accounting constant number := 10;
c_deptno_research constant number := 20;
c_deptno_sales constant number := 30;
c_deptno_operations constant number := 40;
v_last_wage number; --변수 선언
--공용서브프로그램 선언
function get_wage(a.empno number) return number;
procedure raise_bounce(a_empno number, a_amt number);
end;-- 패키지 명세에서는 end 는 있어야 하지만 begin이 없다
위의 예제와 같이 패키지를 사용하기 위해서는 명시가 필요하게 되는데 이때 유의해야 할 점은 마지막이 END로 끝을 맺지만 BEGIN 절은 존재하지 않습니다.
패키지 본체
패키지 본체는 패키지 명세에서 선언만 하고 실체를 정의하지 않은 서브프로그램과 커서를 실제로 정의하는 구역 입니다. 패키지 명세에서 선언한 상수, 타입, 변수, 커서, 서브프로그램 등을 사용할 수 있지만 내부적으로만 사용할 목적의 앞서 열거한 요소들을 추가 선언하는 것이 가능합니다. 패키지 본체의 구조에서는 명세와 달리 꼭 지켜야할 구조 원칙이 있습니다. 요소들 중 서브프로그램이 본체 선언부의 마지막에 놓여야 한다는 원칙인데, 이를 준수하지 않을 경우 해당 패키지는 컴파일 에러를 일으킵니다.
예제를 통해 패키지 본체 구조를 알아 보겠습니다.
create or replace package body PKG_EMP
is
--==========전용상수 선언 ===============
c_null_commission constant number := 10;
c_failed_return_wage constant number := -1;
--==========전용커서 선언 ===============
cursor emp_cursor(a_empno number) is
select sal+nvl(comm, c_null_commission) comm
from emp
where empno = a_empno ;
--==========공용 서브프로그램 정의 ===============
function get_wage(a_empno number) return number
is
begin
for rec in emp_cursor(a_empno)
loop
v_last_wage := rec.comm;
return rec.comm;
end loop;
return c_failed_return_wage;
end;
procedure raise_bounce(a_empno number, a_amt number)
is
v_ename emp.ename%TYPE;
begin
begin
select ENAME
into v_ename
from emp
where empno = a_empno;
exception
when no_data_found then
return;
end;
if a_amt is not null
then
merge into bonus
using dual
on(bonus.ename =v_ename)
when matched then
update set comm =comm +a_amt
when not matched then
insert (ename, comm)
values (v_ename, a_amt);
end if ;
end;
--==========패키지 초기화부 ===============
begin
v_last_wage :=1;
end;
위 예제 선언부 에서는 패키지 명세에 정의되지 않았던 상수 c_null_commission, c_failed_return_wage 와 커서 mp_cursor 가 선언 된것을 확인 할 수 있습니다
--==========전용상수 선언 ===============
c_null_commission constant number := 10;
c_failed_return_wage constant number := -1;
--==========전용커서 선언 ===============
cursor emp_cursor(a_empno number) is
select sal+nvl(comm, c_null_commission) comm
from emp
where empno = a_empno ;
위에서 언급했 듯 이러한 부분이 명세에서 정의되지 않은 본체의 전용 요소가 됩니다. 또한 전체 구조를 살펴 보면 서브프로그램이 가장 아래에 위치하고 있는 모습을 확인 할 수 있습니다 .
패키지 내용 활용하기
패키지에 대한 명세와 본체를 구현 했다면, 이 패키지에서 정의한 내용을 다른 곳에서 활용할 수 있습니다. 간단하게 패키지의 내용을 활용하기 위해선 패키지 명에 '.' 점을 붙이고 해당 요소에 접근하여 사용할 수 있습니다.
ex) 패키지 pkg_emp 변수접근
DECLARE
v_var number;
BEGIN
DBMS_OUTPUT.PUT_LINE('last wage:' || PKG_EMP.v_last_wage);
end;
ex) 패키지 pkg_emp 서브프로그램 호출
DECLARE
v_var number;
BEGIN
v_var := pkg_emp.GET_WAGE(7788);
end;
ex) SQL 에서 패키지 pkg_emp 사용
SELECT pkg_emp.v_last_wage
from dual