Oracle Типи об'єктів PL/SQL: CREATE TYPE з прикладами
⚡ Розумний підсумок
Об'єктні типи в PL/SQL надають об'єктно-орієнтованому програмуванню Oracle, що дозволяє моделювати реальні сутності за допомогою атрибутів та методів. Вони підтримують конструктори, успадкування та порівняння рівності, тому один тип рівня схеми може зберігати та обробляти структуровані дані.

Що таке тип об’єкта в PL/SQL?
Об'єктно-орієнтоване програмування особливо підходить для створення компонентів багаторазового використання та складних застосунків. Програми організовані навколо «об'єктів», а не «дій»; тобто вони розроблені для роботи та взаємодії з цілим об'єктом, а не з окремою дією. Такий підхід дозволяє програмісту заповнювати та маніпулювати деталями на рівні об'єкт-сутність.
На зображенні нижче наведено приклад об'єктного типу, в якому банківський рахунок розглядається як об'єктна сутність. Атрибути об'єкта містять значення — для банківського рахунку це номер рахунку, баланс банківського рахунку тощо — тоді як методи об'єкта описують такі дії, як розрахунок процентної ставки або створення банківської виписки, кожна з яких вимагає виконання певного процесу.
In PL / SQL, об'єктно-орієнтоване програмування базується на типах об'єктів. Тип об'єкта може представляти будь-яку реальну сутність. У розділах нижче розглядаються типи об'єктів, їхні компоненти, а також способи їх створення та використання.
Компоненти типів об'єктів
Об'єктний тип PL/SQL містить переважно два компоненти.
- Attributes
- Члени/Методи
Attributes
Атрибути – це стовпці або поля, в яких зберігаються дані. Кожен атрибут відповідає типу даних, який визначає тип обробки та зберігання для цього атрибута. Атрибут може бути будь-яким допустимим Тип даних PL/SQL, або це може бути об’єкт іншого типу.
Члени/Методи
Члени, або методи, це підпрограми визначені всередині об'єктного типу. Вони не використовуються для зберігання даних; натомість вони визначають обробку, що виконується всередині об'єктного типу, наприклад, перевірку даних перед заповненням об'єкта. Вони оголошуються в специфікації об'єктного типу та визначаються в тілі об'єктного типу. Тіло є необов'язковим: якщо члени відсутні, об'єктний тип не має частини тіла.
Створити об'єкт у Oracle
Тип об'єкта не може бути створений на рівні підпрограми; його можна створити лише на рівні схеми. Після того, як тип об'єкта визначено в схемі, його можна використовувати в підпрограмах. Тип об'єкта створюється за допомогою оператора «CREATE TYPE», а тіло типу можна створити лише після того, як його тип об'єкта існує.
На скріншотах нижче показано синтаксис CREATE TYPE для специфікації об'єкта та синтаксис CREATE TYPE BODY, який визначає його методи.
CREATE TYPE<object_type_name> AS OBJECT ( <attribute_l><datatype>, . . ); / CREATE TYPE BODY<object_type_name> AS OBJECT ( MEMBER[PROCEDURE|FUNCTION]<member_name> IS <declarative section> BEGIN <execution part> END; . . ); /
Пояснення синтаксису:
- Наведений вище синтаксис показує створення ОБ'ЄКТА з атрибутами та ТІЛА ОБ'ЄКТА з методами.
- Методи також можуть бути перевантажені в тілі об’єкта.
Ініціалізація оголошення типу об’єкта
Як і інші компоненти в PL/SQL, типи об'єктів необхідно оголосити перед їх використанням у програмі. Після створення типу об'єкта його можна використовувати в декларативній секції підпрограми для оголошення змінної цього типу об'єкта.
Щоразу, коли змінна оголошується як об'єктний тип, під час виконання створюється новий екземпляр цього об'єктного типу, і на цей новостворений екземпляр посилається ім'я змінної. Таким чином, один об'єктний тип може зберігати кілька значень у різних екземплярах.
На скріншоті нижче показано змінну, що оголошується як об'єктний тип всередині Блок PL/SQL.
DECLARE <variable_name> <object_type_name>; BEGIN . . END; /
Пояснення синтаксису:
- Наведений вище синтаксис показує оголошення a змінна як тип об'єкта в декларативній секції.
Після того, як змінна оголошується як об'єктний тип у підпрограмі, вона атомарно є null — весь об'єкт є null. Його необхідно ініціалізувати значеннями, перш ніж його можна буде використовувати в програмі. Об'єкти ініціалізуються за допомогою конструкторів.
Конструктори – це неявний метод об'єкта, на який можна посилатися з тим самим ім'ям, що й тип об'єкта. На скріншоті нижче показано ініціалізацію екземпляра типу об'єкта.
DECLARE <variable_name> <object_type_name>; BEGIN <variable_name>:=<object_type_name>(); END; /
Пояснення синтаксису:
- Наведений вище синтаксис показує ініціалізацію екземпляра об'єктного типу значенням null.
- Сам об'єкт перестає бути нульовим після ініціалізації, але атрибути всередині об'єкта залишаються нульовими, доки їм не будуть присвоєні значення.
Конструктори
Конструктори – це неявний метод об'єкта, на який можна посилатися з тим самим ім'ям, що й тип об'єкта. Щоразу, коли до об'єкта звертаються вперше, цей конструктор викликається неявно.
Ви також можете ініціалізувати об'єкти за допомогою цих конструкторів. Конструктор можна явно визначити, визначивши член у тілі типу об'єкта з тим самим ім'ям, що й тип об'єкта.
Приклад 1: У наступному прикладі ми використовуємо член об'єктного типу для вставки записів у таблицю emp зі значеннями ('RRR', 1005, 20000, 1000) та ('PPP', 1006, 20000, 1001). Після вставки даних ми відображаємо їх за допомогою члена об'єктного типу. Ми також використовуємо явний конструктор для заповнення ідентифікатора менеджера значенням за замовчуванням 1001 для другого запису.
Ми виконуємо його в наступних кроках.
- Крок 1: Створіть тип об'єкта та тіло типу об'єкта.
- Крок 2: Створіть анонімний блок для виклику типу об'єкта через неявний конструктор для emp_no 1005.
- Крок 3: Створіть анонімний блок для виклику типу об'єкта через явний конструктор для emp_no 1006.
Крок 1) Створіть тип об'єкта та тіло типу об'єкта.
На скріншоті нижче показано створення специфікації типу об'єкта emp_object з її атрибутами та членами.
CREATE TYPE emp_object AS OBJECT( emp_no NUMBER, emp_name VARCHAR2(50), salary NUMBER, manager NUMBER, CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER, p_emp_name VARCHAR2, p_salary NUMBER) RETURN SELF AS RESULT), MEMBER PROCEDURE insert_records, MEMBER PROCEDURE display_records); /
На скріншоті нижче показано тіло типу emp_object, яке створюється за допомогою явного конструктора та процедур-членів.
CREATE OR REPLACE TYPE BODY emp_object AS CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER,p_emp_name VARCHAR2, p_salary NUMBER) RETURN SELF AS RESULT IS BEGIN Dbms_output.put_line('Constructor fired..'); SELF.emp_no:=p_emp_no; SELF.emp_name:=p_emp_name; SELF.salary:=p_salary; SELF.manager:=1001; RETURN; END; MEMBER PROCEDURE insert_records IS BEGIN INSERT INTO emp VALUES(emp_no,emp_name,salary,manager); END; MEMBER PROCEDURE display_records IS BEGIN Dbms_output.put_line('Employee Name:'||emp_name); Dbms_output.put_line('Employee Number:'||emp_no); Dbms_output.put_line('Salary:'||salary); Dbms_output.put_line('Manager:'||manager); END; END; /
Code Пояснення
- Code рядки 1-9: Створення об'єктного типу 'emp_object' з 4 атрибутами та 3 членами. Він містить визначення конструктора лише з 3 параметрами. (Фактичний неявний конструктор містить кількість параметрів, що дорівнює кількості атрибутів, присутніх у об'єктному типі.)
- Code рядок 10: Створення тіла типу.
- Code рядки 11-21: Визначення явного конструктора. Присвоєння значень параметрів атрибутам та призначення атрибуту 'manager' значення за замовчуванням '1001'.
- Code рядки 22-26: Визначення члена 'insert_records', в якому значення атрибутів вставляються в таблицю 'emp'.
- Code рядки 27-34: Визначення члена 'display_records', який відображає значення атрибутів типу об'єкта.
вихід:
Тип створений
Тіло типу створено
Крок 2) Створення анонімного блоку для виклику створеного типу об'єкта через неявний конструктор для emp_no 1005.
На скріншоті нижче показано анонімний блок, який викликає emp_object через неявний конструктор.
DECLARE guru_emp_det emp_object; BEGIN guru_emp_det:=emp_object(1005,'RRR',20000,1000); guru_emp_det.display_records; guru_emp_det.insert_records; COMMIT; END;
Code Пояснення
- Code рядки 37-45: Вставка записів за допомогою неявного конструктора. Виклик конструктора містить фактичну кількість значень атрибутів.
- Code рядок 38: Оголошує 'guru_emp_det' як об'єкт типу 'emp_object'.
- Code рядок 41: Оператор 'guru_emp_det.display_records' викликає член 'display_records', і значення атрибутів відображаються.
- Code рядок 42: Оператор 'guru_emp_det.insert_records' викликає член 'insert_records', і значення атрибутів вставляються в таблицю. Потім блок фіксує (фіксує) зміну. угода.
вихід:
Ім'я працівника: RRR
Кількість працівників: 1005
Зарплата: 20000
Менеджер: 1000
Крок 3) Створення анонімного блоку для виклику створеного типу об'єкта через явний конструктор для emp_no 1006.
На скріншоті нижче показано анонімний блок, який викликає emp_object через явний конструктор з трьома аргументами.
DECLARE guru_emp_det emp_object; BEGIN guru_emp_det:=emp_object(1006,'PPP',20000); guru_emp_det.display_records; guru_emp_det.insert_records; COMMIT; END; /
Вихід
Employee Name:PPP Employee Number:1006 Salary:20000 Manager:1001
Code Пояснення:
- Code рядки 46-53: Вставка запису за допомогою явного конструктора.
- Code рядок 46: Оголошує 'guru_emp_det' як об'єкт типу 'emp_object'.
- Code рядок 50: Оператор 'guru_emp_det.display_records' викликає член 'display_records', і значення атрибутів відображаються.
- Code рядок 51: Оператор 'guru_emp_det.insert_records' викликає член 'insert_records', і значення атрибутів вставляються в таблицю. Оскільки передається лише три аргументи, явний конструктор встановлює ідентифікатор менеджера на значення за замовчуванням 1001.
Успадкування типу об’єкта
Властивість успадкування дозволяє підоб'єктному типу отримувати доступ до всіх атрибутів та членів надоб'єктного типу або батьківського об'єктного типу.
Тип підоб'єкта називається успадкованим типом об'єкта, а тип надоб'єкта — батьківським типом об'єкта. Синтаксис нижче показує, як створювати батьківські та успадковані типи об'єктів. На знімку екрана нижче показано синтаксис батьківського (SUPER) типу, позначений як NOT FINAL.
CREATE TYPE <object_type_name_parent> AS OBJECT ( <attribute_l><datatype>, . . )NOT FINAL; /
Пояснення синтаксису:
- Наведений вище синтаксис показує створення типу SUPER. Речення NOT FINAL дозволяє успадкування типу.
На скріншоті нижче показано успадкований синтаксис типу (SUB), створений за допомогою ключового слова UNDER.
CREATE TYPE<object_type_name_sub>UNDER<object_type_name_parent> ( <attribute_l><datatype>, . ); /
Пояснення синтаксису:
- Наведений вище синтаксис показує створення типу SUB. Він містить усі члени та атрибути батьківського об'єктного типу.
Приклад 1: У наведеному нижче прикладі ми використовуємо властивість успадкування для вставки запису з ідентифікатором менеджера '1002' для запису ('RRR', 1007, 20000). Ми виконуємо програму, виконавши такі кроки.
- Крок 1: Створіть тип SUPER.
- Крок 2: Створіть тип і тіло SUB.
- Крок 3: Створіть анонімний блок для виклику типу SUB.
Крок 1) Створіть тип SUPER або батьківський тип.
На скріншоті нижче показано створення супертипів emp_object за допомогою речення NOT FINAL.
CREATE TYPE emp_object AS OBJECT( emp_no NUMBER, emp_name VARCHAR2(50), salary NUMBER, manager NUMBER, CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER,p_emp_name VARCHAR2(50), p_salary NUMBER)RETURN SELF AS RESULT), MEMBER PROCEDURE insert_records, MEMBER PROCEDURE display_records)NOT FINAL; /
Code Пояснення:
- Code рядки 1-9: Створення об'єктного типу 'emp_object' з 4 атрибутами та 3 членами. Він містить визначення конструктора лише з 3 параметрами. Він був оголошений як 'NOT FINAL', тому є батьківським типом.
Крок 2) Створіть тип SUB під типом SUPER.
На скріншоті нижче показано успадкований тип sub_emp_object та його тіло, що створюється.
CREATE OR REPLACE TYPE sub_emp_object UNDER emp_object (default_manager NUMBER,MEMBER PROCEDURE insert_default_mgr); / CREATE OR REPLACE TYPE BODY sub_emp_object AS MEMBER PROCEDURE insert_default_mgr IS BEGIN INSERT INTO emp VALUES(emp_no,emp_name,salary,manager); END; END; /
Code Пояснення:
- Code рядки 10-13: Створення 'sub_emp_object' як успадкованого типу з одним додатковим атрибутом 'default_manager' та оголошенням процедури-члена.
- Code рядок 14: Створення тіла для успадкованого типу об'єкта.
- Code рядки 16-21: Визначення процедури-члена, яка вставляє записи в таблицю 'emp' зі значеннями з об'єктного типу SUPER, за винятком значення manager. Для значення manager використовується 'default_manager' з типу SUB.
Крок 3) Створення анонімного блоку для виклику типу SUB.
На скріншоті нижче показано анонімний блок, який викликає тип SUB та вставляє ідентифікатор менеджера за замовчуванням.
DECLARE guru_emp_det sub_emp_object; BEGIN guru_emp_det:= sub_emp_object(1007,'RRR',20000,1000,1002); guru_emp_det.insert_default_mgr; COMMIT; END; /
Code Пояснення:
- Code рядок 25: Оголошення 'guru_emp_det' як типу 'sub_emp_object'.
- Code рядок 27: Ініціалізація об'єкта за допомогою неявного конструктора. Конструктор має 5 параметрів (4 атрибути типу PARENT та 1 атрибут типу SUB). Останній параметр (1002) визначає значення атрибута default_manager.
- Code рядок 28: Виклик члена 'insert_default_mgr' для вставки запису з ідентифікатором менеджера за замовчуванням, переданим у конструкторі.
Рівність об'єктів PL/SQL
Екземпляри об'єктів, що належать до одного типу об'єктів, можна порівнювати на рівність. Для цього типу об'єкта потрібен спеціальний метод, який називається методом ORDER.
Цей метод ORDER має бути функцією, яка повертає числовий тип. Він приймає два параметри на вхід (перший параметр: ідентифікатор екземпляра власного об'єкта; другий параметр: ідентифікатор іншого екземпляра об'єкта).
Ідентифікатори двох екземплярів об'єктів порівнюються, і результат повертається у вигляді числа.
- Додатне значення вказує на те, що екземпляр об'єкта SELF більший за інший екземпляр.
- Від'ємне значення вказує на те, що екземпляр об'єкта SELF менший за інший екземпляр.
- Нуль вказує на те, що екземпляр об'єкта SELF дорівнює іншому екземпляру.
- Якщо будь-який з екземплярів має значення null, функція повертає значення null.
На скріншоті нижче показано синтаксис функції-члена ORDER, яку необхідно включити до тіла типу для перевірки рівності.
CREATE TYPE BODY<object_type_name_ 1>AS OBJECT ( ORDER MEMBER FUNCTION match(<parameter> object_type_name_ 1) RETURN INTEGER IS BEGIN IF <attribute_name>parameter <attribute_name>THEN RETURN -1; --any negative number will do ELSIF id>c.id THEN RETURN 1; --any positive number will do ELSE RETURN 0; END IF; END; . . ); /
Пояснення синтаксису:
- Наведений вище синтаксис показує функцію ORDER, яку необхідно включити до тіла типу для перевірки рівності.
- Параметр для цієї функції має бути екземпляром того самого типу об’єкта.
- Функцію можна викликати як “obj_instance_1.match(obj_instance_2)”, і цей вираз повертає показане числове значення, де obj_instance_1 та obj_instance_2 – це екземпляри об’єктного типу.
Приклад 1: У наступному прикладі ми порівнюємо два об'єкти. Ми створюємо два екземпляри та порівнюємо атрибут «зарплата» між ними. Ми робимо це у два кроки.
- Крок 1: Створіть тип та тіло об'єкта.
- Крок 2: Створіть анонімний блок для порівняння екземплярів об'єктів.
Крок 1) Створення типу та тіла об'єкта.
На скріншотах нижче показано специфікацію emp_object_equality та її тіло, яке визначає функцію ORDER, що порівнює атрибут salary.
CREATE TYPE emp_object_equality AS OBJECT( salary NUMBER, ORDER MEMBER FUNCTION equals(c emp_object_equality)RETURN INTEGER); /
CREATE TYPE BODY emp_object_equality AS ORDER MEMBER FUNCTION equals(c emp_object_equality)RETURN INTEGER IS BEGIN IF salary<c.salary THEN RETURN -1; ELSIF salary>c.salary THEN RETURN 1; ELSE RETURN 0; END IF; END; END; /
Code Пояснення:
- Code рядки 1-4: Створення об'єкта типу 'emp_object_equality' з 1 атрибутом та 1 членом.
- Code рядки 6-16: Визначення функції ORDER, яка порівнює атрибут 'salary' екземпляра SELF та екземпляра параметра. Вона повертає від'ємне значення, якщо зарплата SELF менша, додатне значення, якщо зарплата SELF більша, та 0, якщо зарплати рівні.
Code вихід:
Тип створений
Крок 2) Створення анонімного блоку для порівняння екземплярів об'єктів.
На скріншоті нижче показано анонімний блок, який порівнює два екземпляри emp_object_equality за зарплатою.
DECLARE l_obj_1 emp_object_equality; l_obj_2 emp_object_equality; BEGIN l_obj_1:=emp_object_equality(15000); l_obj_2:=emp_object_equality(17000); IF l_obj_1.equals(l_obj_2)>0 THEN Dbms_output.put_line('Salary of first instance is greater'); ELSIF l_obj_1.equals(l_obj_2)<0 THEN Dbms_output.put_line('Salary of second instance is greater'); ELSE Dbms_output.put_line('Salaries are equal'); END IF; END; /
Вихід
Salary of second instance is greater
Code Пояснення:
- Code рядок 20: Оголошення 'l_obj_1' типу 'emp_object_equality'.
- Code рядок 21: Оголошення 'l_obj_2' типу 'emp_object_equality'.
- Code рядок 23: Ініціалізація 'l_obj_1' значенням зарплати '15000'.
- Code рядок 24: Ініціалізація 'l_obj_2' значенням зарплати '17000'.
- Code рядки 25-33: Друк повідомлення на основі числа, повернутого функцією ORDER.


















