Oracle Пакет PL/SQL: тип, специфікація, тіло [Приклад]

⚡ Розумний підсумок

Пакети PL/SQL групують пов'язані процедури, функції, змінні, курсори та винятки в один об'єкт схеми зі специфікацією та тілом. Специфікація оголошує публічний інтерфейс, тоді як тіло містить приватну реалізацію, покращуючи модульність та продуктивність.

  • 📦 Визначення пакета: Пакет — це логічна групаping пов'язаних підпрограм та об'єктів, скомпільованих та збережених як єдиний об'єкт бази даних.
  • 📋 Специфікація пакету: Оголошує публічні змінні, курсори, типи, винятки, процедури та функції, доступні ззовні пакета.
  • 🧱 Тіло пакета: Визначає кожен елемент, оголошений у специфікації, а також приватні елементи, які можна викликати лише зсередини пакета.
  • 🔁 Перевантаження: Кілька підпрограм можуть мати одне й те саме ім'я, якщо їхній номер параметра, типи параметрів або тип повернення відрізняються.
  • 🔗 Посилання та залежність: Публічні елементи викликаються як package_name.element_name, а тіло залежить від специфікації.
  • 🤖 Допомога AI: Помічники ШІ, такі як GitHub Copilot, створюють специфікації чернеток пакетів, тіла та перевантажені підпрограми з коментаря.

Oracle Огляд специфікації пакета PL/SQL та структури його тіла

Що таке Package in 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.

Створення специфікації пакета guru99_get_set з використанням set_record та get_record у 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: Було здійснено виклик функції 'set_record' пакета guru99_get_set. Тепер екземпляр пакета створено, і він зберігатиметься до кінця сеансу. Частина ініціалізації пакета виконується, оскільки це перший виклик пакета, а запис вставляється елементом 'set_record' у таблицю.
  • Code рядок 41: Виклик елемента 'get_record' для відображення деталей вставленого співробітника. До пакета звертаються вдруге під час цього виклику, але частина ініціалізації не виконується повторно, оскільки пакет вже ініціалізовано в цьому сеансі.
  • Code рядки 42-45: Друк відомостей про співробітника.

Залежність у пакетах

Оскільки пакет є логічною групоюping З пов'язаних речей, він має деякі залежності. Нижче наведено залежності, про які слід подбати.

  • Специфікація — це окремий об'єкт.
  • Тіло пакета залежить від специфікації.
  • Тіло пакета можна скомпілювати окремо. Щоразу, коли компілюється специфікація, тіло потрібно перекомпілювати, оскільки воно стане недійсним.
  • Підпрограма в тілі пакета, яка залежить від приватного елемента, повинна бути визначена лише після оголошення приватного елемента.
  • Об'єкти бази даних, на які посилаються в специфікації та тілі пакета, повинні бути в дійсному стані на момент компіляції пакета.

Інформація про пакет

Після створення пакета інформація про пакет, така як джерело пакета, деталі підпрограми та деталі перевантаження, доступна в Oracle таблиці словника даних.

У таблиці нижче наведено таблицю словника даних та інформацію про пакет, доступну в кожній таблиці.

Назва таблиці Опис Запит
ВСІ_ОБ'ЄКТИ Надає деталі пакета, такі як object_id, creation_date, last_ddl_time тощо. Він містить об'єкти, створені всіма користувачами. SELECT * FROM all_objects where object_name =' '
ОБ'ЄКТИ_КОРИСТУВАЧА Надає деталі пакета, такі як object_id, creation_date, last_ddl_time тощо. Містить об'єкти, створені поточним користувачем. SELECT * FROM user_objects, де object_name =' '
ALL_SOURCE Надає джерело об’єктів, створених усіма користувачами. SELECT * FROM all_source where name=' '
USER_SOURCE Надає джерело об’єктів, створених поточним користувачем. SELECT * FROM user_source where name=' '
УСІ_ПРОЦЕДУРИ Надає деталі підпрограми, такі як object_id, деталі перевантаження тощо, створені всіма користувачами. SELECT * FROM all_procedures Де object_name=' '
USER_PROCEDURES Надає такі деталі підпрограми, як object_id, деталі перевантаження тощо, створені поточним користувачем. SELECT * FROM user_procedures Де object_name=' '

UTL_FILE – Огляд

UTL_FILE — це окремий пакет утиліт, що надається Oracle для виконання спеціальних завдань. Він використовується переважно для читання та запису файлів операційної системи з пакетів PL/SQL або підпрограм. Він має окремі функції для введення інформації у файли та отримання інформації з файлів. Він також дозволяє читати та записувати у рідному наборі символів.

Програміст може використовувати це для запису файлів операційної системи будь-якого типу, і файл буде записано безпосередньо на сервер бази даних. Ім'я та шлях до каталогу згадуються під час написання.

Поширені запитання

Пакети забезпечують модульність, приховування інформації та спрощують проектування застосунків. Специфікація надає публічний інтерфейс, тоді як тіло приховує реалізацію. Oracle завантажує пакет у пам'ять під час першого виклику, тому наступні виклики підпрограм уникають операцій вводу/виводу з диска та виконуються швидше.

Пакет об'єднує багато пов'язаних підпрограми та спільні об'єкти під одним іменем, що відокремлює публічну специфікацію від приватного тіла. Автономна процедура або функція — це єдиний, незалежний об'єкт схеми без такого поділу на інтерфейс та реалізацію.

Так, якщо специфікація оголошує лише змінні, константи, типи або винятки. Тіло стає обов'язковим, як тільки специфікація оголошує будь-яку процедуру, функцію або курсор, оскільки тіло має забезпечувати їхню реалізацію. В іншому випадку специфікація може існувати самостійно.

Використовуйте 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переглянути згенеровані межі, блок ініціалізації та обробку винятків перед розгортанням.

Помічники штучного інтелекту сканують пакет на наявність недійсних станів, відсутніх визначень тіла та ланцюжків залежностей, які розриваються під час зміни специфікації. Цей огляд машинного навчання виявляє неоднозначні перевантажені підпрограми та ризики перекомпіляції, перш ніж пакет потрапить у робоче середовище.

Підсумуйте цей пост за допомогою: