Oracle PL/SQL 패키지: 유형, 사양, 본문 [예]

⚡ 스마트 요약

PL/SQL 패키지는 관련된 프로시저, 함수, 변수, 커서 및 예외를 명세와 본문을 포함하는 하나의 스키마 객체로 그룹화합니다. 명세는 공개 인터페이스를 선언하고, 본문은 비공개 구현을 담아 모듈성과 성능을 향상시킵니다.

  • 📦 패키지 정의: 패키지는 논리적 그룹입니다.ping 관련된 하위 프로그램과 객체들이 하나의 데이터베이스 객체로 컴파일되어 저장됩니다.
  • 📋 패키지 사양: 패키지 외부에서 접근 가능한 공용 변수, 커서, 타입, 예외, 프로시저 및 함수를 선언합니다.
  • 🧱 패키지 본체: 명세에 선언된 모든 요소와 패키지 내부에서만 호출 가능한 비공개 요소를 정의합니다.
  • 🔁 과부하 : 여러 하위 프로그램이 매개변수 개수, 매개변수 유형 또는 반환 유형이 서로 다르더라도 하나의 이름을 공유할 수 있습니다.
  • 🔗 참조 및 의존 관계: 공개 요소는 package_name.element_name 형식으로 호출되며, 본문은 명세에 따라 달라집니다.
  • 🤖 AI 지원: GitHub Copilot과 같은 AI 도우미는 댓글을 기반으로 패키지 사양, 본문 및 오버로드된 서브프로그램을 작성합니다.

Oracle PL/SQL 패키지 사양 및 본문 구조 개요

패키지란 무엇입니까? Oracle?

Oracle PL / SQL 패키지는 논리적 그룹입니다.ping 관련된 하위 프로그램 (프로시저/함수)를 단일 요소로 통합합니다. 패키지는 컴파일되어 데이터베이스 객체로 저장되며, 나중에 재사용할 수 있습니다.

패키지 구성요소

PL/SQL 패키지는 두 가지 구성 요소로 이루어져 있습니다.

  • 패키지 사양
  • 패키지 본체

패키지 사양

패키지 사양은 모든 공개 항목에 대한 선언으로 구성됩니다. 변수, 커서객체, 프로시저, 함수 및 예외.

다음은 패키지 사양의 몇 가지 특징입니다.

  • 명세에 선언된 요소는 패키지 외부에서 접근할 수 있습니다. 이러한 요소를 공용 요소라고 합니다.
  • 패키지 명세는 독립적인 요소이므로 패키지 본문 없이 단독으로 존재할 수 있습니다.
  • 패키지가 참조될 때마다 해당 세션에 대한 패키지 인스턴스가 생성됩니다.
  • 세션에 대한 인스턴스가 생성된 후 해당 인스턴스에서 시작된 모든 패키지 요소는 세션이 끝날 때까지 유효합니다.

통사론

CREATE [OR REPLACE] PACKAGE <package_name> 
IS
<sub_program and public element declaration>
.
.
END <package name>

위 구문은 패키지 명세 생성 과정을 보여줍니다.

패키지 본체

패키지 본문은 패키지 명세에 포함된 모든 요소의 정의로 구성됩니다. 또한 명세에 선언되지 않은 요소의 정의도 포함할 수 있는데, 이러한 요소를 비공개 요소라고 하며 패키지 내부에서만 호출할 수 있습니다.

아래는 패키지 본체의 특징입니다.

  • 이 파일에는 명세에 선언된 모든 하위 프로그램/커서에 대한 정의가 포함되어야 합니다.
  • 또한 명세에 명시되지 않은 하위 프로그램이나 다른 요소들을 더 많이 포함할 수 있습니다. 이러한 요소들을 비공개 요소라고 합니다.
  • 이는 종속 객체이며, 패키지 사양에 따라 달라집니다.
  • 패키지 본문의 상태는 명세가 컴파일될 때마다 '유효하지 않음'이 됩니다. 따라서 명세 컴파일 후에는 매번 다시 컴파일해야 합니다.
  • 전용 요소는 패키지 본문에서 사용되기 전에 먼저 정의되어야 합니다.
  • 패키지 본문의 첫 번째 부분은 전역 선언 부분입니다. 여기에는 패키지 전체에서 볼 수 있는 변수, 커서 및 비공개 요소(전방 선언)가 포함됩니다.
  • 패키지의 마지막 부분은 패키지 초기화 부분으로, 세션에서 패키지가 처음 참조될 때마다 한 번 실행됩니다.

구문 :

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<global_declaration part>
<Private element definition>
<sub_program and public element definition>
.
<Package Initialization> 
END <package_name>

위 구문은 패키지 본문을 생성하는 방법을 보여줍니다.

이제 프로그램에서 패키지 요소를 참조하는 방법을 살펴보겠습니다.

패키지 요소 참조

패키지 내에 요소들을 선언하고 정의한 후에는, 해당 요소들을 사용하기 위해 참조해야 합니다.

패키지의 모든 공개 요소는 패키지 이름 뒤에 요소 이름을 마침표로 구분하여 호출하는 방식으로 참조할 수 있습니다. 예: ' . '.

패키지의 공개 변수도 같은 방식으로 값을 할당하고 가져오는 데 사용할 수 있습니다. 즉, ' . '.

PL/SQL에서 패키지 생성

PL/SQL에서는 세션 내에서 패키지를 참조하거나 호출할 때마다 해당 패키지에 대한 새 인스턴스가 생성됩니다.

Oracle '패키지 초기화'를 통해 이 인스턴스 생성 시 패키지 요소를 초기화하거나 모든 활동을 수행하는 기능을 제공합니다.

이는 패키지의 모든 요소를 ​​정의한 후 패키지 본문에 작성되는 실행 블록일 뿐입니다. 이 블록은 세션에서 패키지가 처음 참조될 때마다 실행됩니다.

아래 스크린샷은 패키지를 생성할 때 패키지 초기화 블록이 패키지 본문 안에 어떻게 배치되는지를 보여줍니다.

패키지 본문에 패키지 초기화 블록을 포함하여 PL/SQL 패키지를 생성하는 방법

통사론

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<Private element definition>
<sub_program and public element definition>
.
BEGIN
<Package Initialization> 
END <package_name>

위 구문은 패키지 본문의 패키지 초기화 정의를 보여줍니다.

전방 선언

패키지 내에서의 전방 선언 또는 참조는 비공개 요소를 별도로 선언하고 패키지 본문의 뒷부분에서 정의하는 것과 같습니다.

비공개 요소는 패키지 본문에 이미 선언된 경우에만 참조할 수 있습니다. 이러한 이유로 전방 선언이 사용됩니다. 하지만 대부분의 경우 비공개 요소는 패키지 본문의 앞부분에서 선언 및 정의되므로 전방 선언은 드물게 사용됩니다.

전방 선언은 다음에서 제공하는 옵션입니다. Oracle필수 사항은 아니며, 사용 여부는 프로그래머의 필요에 따라 결정됩니다.

아래 스크린샷은 비공개 요소가 어떻게 전방 선언되고 이후 패키지 본문에서 정의되는지를 보여줍니다.

개인 요소의 전방 선언 Oracle PL/SQL 패키지 본문

구문 :

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<Private element declaration>
.
.
.
<Public element definition that refer the above private element>
.
.
<Private element definition> 
.
BEGIN
<package_initialization code>; 
END <package_name>

위의 구문은 전방 선언을 보여줍니다. 개인 요소는 패키지의 전방 부분에서 별도로 선언되고, 후반 부분에서 정의되었습니다.

패키지 내 커서 사용법

다른 요소들과 달리, 패키지 내부에서 커서를 사용할 때는 주의해야 합니다.

커서가 패키지 사양이나 패키지 본문의 전역 부분에 정의된 경우, 커서는 한 번 열리면 세션이 끝날 때까지 유지됩니다.

따라서 커서를 참조하기 전에 항상 커서 속성 '%ISOPEN'을 사용하여 커서의 상태를 확인해야 합니다.

과부하

오버로딩이란 동일한 이름을 가진 여러 개의 서브프로그램을 사용하는 개념입니다. 이러한 서브프로그램들은 매개변수의 개수, 매개변수의 데이터 유형 또는 반환 타입에서 서로 다릅니다. 다시 말해, 이름은 같지만 매개변수의 개수, 데이터 유형 또는 반환 타입이 다른 서브프로그램들을 오버로딩이라고 합니다.

이 방법은 여러 하위 프로그램이 동일한 작업을 수행해야 하지만 각 하위 프로그램을 호출하는 방식이 서로 달라야 할 때 유용합니다. 이 경우 하위 프로그램 이름은 모두 동일하게 유지되고, 매개변수는 호출문에 따라 변경됩니다.

예 1 : 이 예제에서는 'emp' 테이블에서 직원의 정보를 가져오고 설정하는 패키지를 생성합니다. `get_record` 함수는 주어진 직원 번호에 대한 레코드 유형을 반환하고, `set_record` 프로시저는 해당 레코드 유형을 `emp' 테이블에 삽입합니다.

1단계) 패키지 사양 생성

아래 스크린샷은 guru99_get_set 패키지 사양이 생성되는 과정을 보여줍니다. Oracle.

set_record 및 get_record를 사용하여 guru99_get_set 패키지 사양을 생성합니다. Oracle

CREATE OR REPLACE PACKAGE guru99_get_set
IS
PROCEDURE set_record (p_emp_rec IN emp%ROWTYPE);
FUNCTION get_record (p_emp_no IN NUMBER) RETURN emp%ROWTYPE;
END guru99_get_set;
/

출력:

Package created

Code 설명

  • Code 1-5행: 프로시저 하나와 함수 하나로 구성된 guru99_get_set 패키지 사양을 작성했습니다. 이 두 가지는 이제 해당 패키지의 공개 요소입니다.

단계 2) 패키지에는 패키지 본문이 포함되어 있으며, 이 본문에는 모든 프로시저와 함수의 실제 정의가 포함됩니다. 이 단계에서는 패키지 본문을 생성합니다.

아래 스크린샷은 guru99_get_set 패키지 본문 정의를 보여줍니다. Oracle.

guru99_get_set 패키지 본문을 set_record, get_record 및 초기화 블록으로 정의합니다.

CREATE OR REPLACE PACKAGE BODY guru99_get_set
IS
PROCEDURE set_record(p_emp_rec IN emp%ROWTYPE)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO emp
VALUES(p_emp_rec.emp_name,p_emp_rec.emp_no, p_emp_rec.salary,p_emp_rec.manager);
COMMIT;
END set_record;
FUNCTION get_record(p_emp_no IN NUMBER)
RETURN emp%ROWTYPE
IS
l_emp_rec emp%ROWTYPE;
BEGIN
SELECT * INTO l_emp_rec FROM emp where emp_no=p_emp_no;
RETURN l_emp_rec;
END get_record;
BEGIN
dbms_output.put_line('Control is now executing the package initialization part');
END guru99_get_set;
/

출력:

Package body created

Code 설명

  • Code 7행: 패키지 본문을 생성합니다.
  • Code 9-16행: 명세에 선언된 'set_record' 요소를 정의합니다. 이는 PL/SQL에서 독립형 프로시저를 정의하는 것과 동일합니다.
  • Code 17-24행: 'get_record' 요소를 정의하는 것은 독립적인 함수를 정의하는 것과 같습니다.
  • Code 25-26행: 패키지 초기화 부분을 정의합니다.

단계 3) 위에서 생성한 패키지를 참조하여 레코드를 삽입하고 표시하는 익명 블록을 생성합니다.

아래 스크린샷은 패키지를 호출하는 익명 코드 블록과 그 출력 결과를 보여줍니다. Oracle.

익명 블록이 guru99_get_set을 호출하여 직원 기록을 삽입하고 출력합니다.

DECLARE
l_emp_rec emp%ROWTYPE;
l_get_rec emp%ROWTYPE;
BEGIN
dbms_output.put_line('Insert new record for employee 1004');
l_emp_rec.emp_no:=1004;
l_emp_rec.emp_name:='CCC';
l_emp_rec.salary:=20000;
l_emp_rec.manager:='BBB';
guru99_get_set.set_record(l_emp_rec);
dbms_output.put_line('Record inserted');
dbms_output.put_line('Calling get function to display the inserted record');
l_get_rec:=guru99_get_set.get_record(1004);
dbms_output.put_line('Employee name: '||l_get_rec.emp_name);
dbms_output.put_line('Employee number:'||l_get_rec.emp_no);
dbms_output.put_line('Employee salary:'||l_get_rec.salary);
dbms_output.put_line('Employee manager:'||l_get_rec.manager);
END;
/

출력:

Insert new record for employee 1004
Control is now executing the package initialization part
Record inserted
Calling get function to display the inserted record
Employee name: CCC
Employee number: 1004
Employee salary: 20000
Employee manager: BBB

Code 설명 :

  • Code 34-37행: 패키지의 'set_record' 요소를 호출하기 위해 익명 블록에서 레코드 유형 변수에 데이터를 채웁니다.
  • Code 38행: guru99_get_set 패키지의 'set_record' 함수를 호출했습니다. 이제 패키지 인스턴스가 생성되었으며 세션이 종료될 때까지 유지됩니다. 패키지를 처음 호출하는 것이므로 패키지 초기화 부분이 실행되고, 'set_record' 요소에 의해 레코드가 테이블에 삽입됩니다.
  • Code 41행: 'get_record' 요소를 호출하여 삽입된 직원의 세부 정보를 표시합니다. 이 호출 중에 패키지가 두 번째로 참조되지만, 패키지가 이미 이 세션에서 초기화되었으므로 초기화 부분은 다시 실행되지 않습니다.
  • Code 42-45행: 직원 세부 정보를 인쇄합니다.

패키지의 종속성

패키지는 논리적 그룹이기 때문에ping 관련 항목이므로 몇 가지 의존성이 있습니다. 다음은 주의해야 할 의존성입니다.

  • 명세서는 독립적인 객체입니다.
  • 패키지 본체는 사양에 따라 달라집니다.
  • 패키지 본문은 별도로 컴파일할 수 있습니다. 명세가 컴파일될 때마다 본문도 다시 컴파일해야 합니다. 그렇지 않으면 본문이 무효화됩니다.
  • 패키지 본문 내에서 비공개 요소에 의존하는 서브프로그램은 해당 비공개 요소 선언 이후에만 정의되어야 합니다.
  • 명세 및 본문에서 참조되는 데이터베이스 객체는 패키지 컴파일 시점에 유효한 상태여야 합니다.

패키지 정보

패키지가 생성되면 패키지 소스, 서브프로그램 세부 정보, 오버로드 세부 정보와 같은 패키지 정보를 확인할 수 있습니다. Oracle 데이터 사전 테이블.

아래 표는 데이터 사전 테이블과 각 테이블에서 사용할 수 있는 패키지 정보를 보여줍니다.

테이블 이름 기술설명 질문
모든 객체 객체 ID, 생성 날짜, 마지막 DDL 시간 등과 같은 패키지 세부 정보를 제공합니다. 모든 사용자가 생성한 객체가 포함되어 있습니다. SELECT * FROM all_objects 여기서 object_name =' '
사용자 객체 객체 ID, 생성 날짜, 마지막 DDL 시간 등과 같은 패키지 세부 정보를 제공합니다. 현재 사용자가 생성한 객체가 포함되어 있습니다. SELECT * FROM user_objects 여기서 object_name =' '
ALL_소스 모든 사용자가 생성한 객체의 소스를 제공합니다. SELECT * FROM all_source 여기서 이름=' '
USER_SOURCE 현재 사용자가 만든 개체의 소스를 제공합니다. SELECT * FROM user_source 여기서 이름=' '
ALL_PROCEDURES 모든 사용자가 생성한 서브프로그램의 object_id, 오버로드 정보 등과 같은 세부 정보를 제공합니다. SELECT * FROM all_procedures WHERE object_name=' '
USER_PROCEDURES 현재 사용자가 생성한 하위 프로그램의 세부 정보(object_id, 오버로드 세부 정보 등)를 제공합니다. SELECT * FROM user_procedures WHERE object_name=' '

UTL_FILE - 개요

UTL_FILE은 별도의 유틸리티 패키지로 제공됩니다. Oracle 특수한 작업을 수행하기 위해 사용됩니다. 주로 PL/SQL 패키지 또는 서브프로그램에서 운영 체제 파일을 읽고 쓰는 데 사용됩니다. 파일에 정보를 입력하고 파일에서 정보를 가져오는 별도의 함수를 제공하며, 네이티브 문자 집합으로 읽고 쓰는 것도 가능합니다.

프로그래머는 이 기능을 사용하여 모든 유형의 운영 체제 파일을 작성할 수 있으며, 해당 파일은 데이터베이스 서버에 직접 기록됩니다. 파일 이름과 디렉터리 경로는 작성 시점을 기준으로 지정됩니다.

자주 묻는 질문

패키지는 모듈화, 정보 은닉 및 간편한 애플리케이션 설계를 제공합니다. 명세는 공개 인터페이스를 제공하고 본문은 구현을 숨깁니다. Oracle 첫 호출 시 패키지를 메모리에 로드하므로 이후 서브프로그램 호출 시 디스크 I/O를 피할 수 있어 실행 속도가 빨라집니다.

패키지는 여러 관련 항목을 묶습니다. 하위 프로그램 공유 객체는 하나의 이름 아래에 있으며, 공개 사양과 비공개 본문을 분리합니다. 독립 실행형 프로시저 또는 함수는 인터페이스-구현 분리가 없는 단일 독립 스키마 객체입니다.

네, 명세에 변수, 상수, 타입 또는 예외만 선언된 경우에는 본문이 필수적입니다. 명세에 프로시저, 함수 또는 커서가 선언되면 본문에서 해당 구현을 제공해야 하므로 본문이 필수적입니다. 그렇지 않은 경우에는 명세만으로 충분할 수 있습니다.

DROP PACKAGE를 사용하여 패키지 명세와 본문을 모두 제거하고, DROP PACKAGE BODY를 사용하여 본문만 제거합니다. 유효하지 않은 패키지를 다시 컴파일하려면 ALTER PACKAGE package_name COMPILE을 사용하고, 변경 후 본문만 다시 빌드하려면 COMPILE BODY를 사용합니다.

%ROWTYPE 속성은 다음을 선언합니다. 기록 해당 필드가 emp 테이블의 열과 일치하도록 합니다. emp%ROWTYPE을 사용하면 get_record 및 set_record 매개변수가 테이블 구조와 일치하게 유지되므로 열 변경 시 코드 수정 횟수가 줄어듭니다.

예. 패키지를 참조하는 각 세션은 고유한 인스턴스화 및 패키지 상태를 가지며, 이는 해당 세션이 지속되는 동안 유지됩니다. 본문을 다시 컴파일하면 해당 상태가 삭제되고 다음 호출 시 ORA-04068 오류가 발생합니다.

예. GitHub 부조종사 주석에서 패키지 사양, 일치하는 본문 및 오버로드된 서브프로그램의 초안을 작성하고 %ROWTYPE 매개변수를 제안합니다. Rev배포하기 전에 생성된 경계, 초기화 블록 및 예외 처리를 확인하십시오.

AI 어시스턴트는 패키지를 검사하여 유효하지 않은 상태, 누락된 본문 정의, 사양 변경 시 깨지는 종속성 체인을 찾아냅니다. 이러한 머신러닝 기반 검토를 통해 패키지가 프로덕션 환경에 배포되기 전에 모호한 오버로드된 서브프로그램과 재컴파일 위험을 미리 파악할 수 있습니다.

이 게시물을 요약하면 다음과 같습니다.