Oracle PL/SQL типове обекти: CREATE TYPE с примери

⚡ Умно обобщение

Обектните типове в PL/SQL предлагат обектно-ориентираното програмиране Oracle, което ви позволява да моделирате реални обекти с атрибути и методи. Те поддържат конструктори, наследяване и сравнение на равенство, така че един тип на ниво схема може да съхранява и обработва структурирани данни.

  • 🧱 Компоненти на типа обект: Обектният тип комбинира атрибути, които съхраняват данни, и членове или методи, които определят неговата логика на обработка.
  • 🏗️ Създаване на обект: Типовете обекти се създават на ниво схема с CREATE TYPE, а техните методи се дефинират в отделен CREATE TYPE BODY.
  • 🔧 Конструктори: Всеки тип обект има имплицитен конструктор, наречен на името на типа, и можете да дефинирате експлицитен конструктор, за да зададете стойности по подразбиране.
  • 🧬 наследство: Родителският тип NOT FINAL се разширява с UNDER, така че подтипът наследява всички родителски атрибути и членове.
  • равенство: Член-функцията ORDER сравнява два екземпляра на обект и връща отрицателно, нула или положително число.
  • 🤖 AI помощ: AI асистенти, като например GitHub Copilot, изготвят CREATE TYPE дефиниции, конструктори и ORDER методи от коментар.

Oracle PL/SQL обектни типове, показващи CREATE TYPE с атрибути и методи

Какво е тип обект в PL/SQL?

Обектно-ориентираното програмиране е особено подходящо за изграждане на компоненти за многократна употреба и сложни приложения. Програмите са организирани около „обекти“, а не около „действия“; тоест, те са проектирани да работят и да взаимодействат с цял обект, а не с едно-единствено действие. Този подход позволява на програмиста да попълва и манипулира детайли на ниво обект-ентитет.

Картината по-долу показва пример за тип обект, в който банкова сметка се третира като обектна единица. Атрибутите на обекта съдържат стойности – за банкова сметка това са номерът на сметката, банковото салдо и т.н. – докато методите на обекта описват действия като изчисляване на лихвения процент или генериране на банково извлечение, всяко от които изисква завършване на определен процес.

Банкова сметка, моделирана като обектен тип с атрибути и методи в PL/SQL

In PL / SQL, обектно-ориентираното програмиране се основава на обектни типове. Обектният тип може да представлява всеки реален обект. Разделите по-долу разглеждат обектните типове, техните компоненти и как да ги създавате и използвате.

Компоненти на типовете обекти

PL/SQL обектният тип съдържа основно два компонента.

  1. Атрибути
  2. Членове/Методи

Атрибути

Атрибутите са колоните или полетата, в които се съхраняват данните. Всеки атрибут е съпоставен с типа данни, който определя типа на обработка и съхранение за този атрибут. Атрибутът може да бъде от всякакъв валиден тип. PL/SQL тип данни, или може да бъде от друг тип обект.

Членове/Методи

Членовете или методите са подпрограми дефинирани вътре в обектния тип. Те не се използват за съхраняване на данни; вместо това, те дефинират обработката, извършвана вътре в обектния тип - например, валидиране на данни преди попълване на обекта. Те се декларират в спецификацията на обектния тип и се дефинират в тялото на обектния тип. Тялото е незадължително: ако няма членове, обектният тип няма част от тялото.

Създаване на обект в Oracle

Обектен тип не може да бъде създаден на ниво подпрограма; той може да бъде създаден само на ниво схема. След като обектният тип е дефиниран в схемата, той може да се използва в подпрограми. Обектният тип се създава с помощта на оператора „CREATE TYPE“, а тялото на типа може да бъде създадено само след като неговият обектен тип съществува.

Снимките на екрана по-долу показват синтаксиса на CREATE TYPE за спецификацията на обекта и синтаксиса на CREATE TYPE BODY, който дефинира неговите методи.

Синтаксис на CREATE TYPE, дефиниращ спецификация на обект с атрибути в Oracle Синтаксис на CREATE TYPE BODY, дефиниращ методите на PL/SQL обектен тип

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 блок.

Деклариране на променлива от обектен тип в декларативен раздел на PL/SQL блок

DECLARE
<variable_name> <object_type_name>;
BEGIN
.
.
END;
/

Обяснение на синтаксиса:

  • Синтаксисът по-горе показва декларацията на a променлив като обектен тип в декларативната секция.

След като променливата бъде декларирана като обектен тип в подпрограма, тя е атомарно null - целият обект е null. Тя трябва да бъде инициализирана със стойности, преди да може да бъде използвана в програмата. Обектите се инициализират с помощта на конструктори.

Конструкторите са имплицитният метод на обект, към който може да се обърнем със същото име като типа на обекта. Снимката на екрана по-долу показва инициализацията на екземпляр на тип обект.

Инициализиране на екземпляр на обектен тип с null, използвайки неговия конструктор

DECLARE
<variable_name> <object_type_name>; 
BEGIN
<variable_name>:=<object_type_name>();
END;
/

Обяснение на синтаксиса:

  • Синтаксисът по-горе показва инициализацията на екземпляра на обектния тип с null стойност.
  • Самият обект вече не е null, след като бъде инициализиран, но атрибутите вътре в обекта остават null, докато не им бъдат присвоени стойности.

конструкторите

Конструкторите са имплицитният метод на обект, към който може да се обърнем със същото име като типа на обекта. Всеки път, когато обектът се обърне за първи път, този конструктор се извиква имплицитно.

Можете също да инициализирате обекти, използвайки тези конструктори. Конструктор може да бъде дефиниран изрично чрез дефиниране на член в тялото на обектния тип със същото име като обектния тип.

Пример 1: В следващия пример използваме члена от тип обект, за да вмъкнем записи в emp таблицата със стойностите ('RRR', 1005, 20000, 1000) и ('PPP', 1006, 20000, 1001). След като данните бъдат вмъкнати, ги показваме, използвайки члена от тип обект. Също така използваме експлицитен конструктор, за да попълним идентификатора на мениджъра със стойността по подразбиране 1001 за втория запис.

Изпълняваме го в следните стъпки.

  • Стъпка 1: Създайте типа обект и тялото на типа обект.
  • Стъпка 2: Създайте анонимен блок, който да извиква типа обект чрез имплицитния конструктор за emp_no 1005.
  • Стъпка 3: Създайте анонимен блок, който да извиква типа обект чрез явния конструктор за emp_no 1006.

Стъпка 1) Създайте тип обект и тяло на тип обект.

Екранната снимка по-долу показва как се създава спецификацията на обектния тип emp_object с нейните атрибути и членове.

Създаване на спецификация на обектен тип 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, което се създава с помощта на явния конструктор и процедурите-членове.

Дефиниране на тялото на типа 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 чрез имплицитния конструктор.

Анонимен блок, извикващ emp_object чрез имплицитния конструктор за emp_no 1005

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 XNUMX

Мениджър: 1000

Стъпка 3) Създаване на анонимен блок за извикване на създадения тип обект чрез явния конструктор за emp_no 1006.

Екранната снимка по-долу показва анонимния блок, който извиква emp_object чрез явния конструктор с три аргумента.

Анонимен блок, извикващ emp_object чрез явния конструктор за emp_no 1006

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 за тип родителски обект NOT FINAL, използван при наследяване

CREATE TYPE <object_type_name_parent> AS OBJECT
(
<attribute_l><datatype>,
.
.
)NOT FINAL;
/

Обяснение на синтаксиса:

  • Синтаксисът по-горе показва създаването на типа SUPER. Клаузата NOT FINAL позволява наследяването на типа.

Екранната снимка по-долу показва наследения синтаксис на типа (SUB), създаден с ключовата дума UNDER.

Синтаксис CREATE TYPE 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 тип или Parent тип.

Екранната снимка по-долу показва как супертипът emp_object се създава с клаузата NOT FINAL.

Създаване на супертип 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 и неговото тяло, което се създава.

Създаване на наследения тип sub_emp_object и неговото тяло с insert_default_mgr

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 и вмъква идентификатора на мениджъра по подразбиране.

Анонимен блок, извикващ типа sub_emp_object, за да вмъкне идентификатор на мениджър по подразбиране

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 обекта е по-малък от другия екземпляр.
  • Нулата показва, че екземплярът на SELF обекта е равен на другия екземпляр.
  • Ако някой от екземплярите е null, функцията връща null.

Екранната снимка по-долу показва синтаксиса на член-функцията ORDER, която трябва да бъде включена в тялото на типа за проверката за равенство.

Синтаксисът на член-функцията 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, която сравнява атрибута заплата.

Създаване на спецификация на обектен тип emp_object_equality с функция ORDER Дефиниране на тялото на типа emp_object_equality, което сравнява атрибута заплата

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, която сравнява атрибута „заплата“ на инстанцията SELF и инстанцията на параметъра. Тя връща отрицателна стойност, ако заплатата на SELF е по-малка, положителна стойност, ако заплатата на SELF е по-голяма, и 0, ако заплатите са равни.

Code Изход:

Типът е създаден

Стъпка 2) Създаване на анонимния блок за сравняване на екземплярите на обектите.

Снимката на екрана по-долу показва анонимния блок, който сравнява два екземпляра на emp_object_equality по заплата.

Анонимен блок, сравняващ два екземпляра на 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.

Въпроси и Отговори

Обектният тип моделира единична реална същност с атрибути и методи. колекция — VARRAY, вложена таблица или асоциативен масив — съдържа много елементи от един тип данни. Обектните типове описват структура и поведение, докато колекциите съхраняват множество стойности.

И двата метода сравняват екземпляри на обекти. MAP методът връща единична скаларна стойност, която Oracle използва за сортиране или сравняване на обекти, докато методът ORDER сравнява директно два екземпляра и връща отрицателно, нула или положително число. Типът може да дефинира единия или другия, не и двата.

Да. Можете да създадете таблица с обекти, където всеки ред е екземпляр на обект, или да използвате тип обект като тип данни на колона на таблица. Това позволява Oracle запазване на структурирани обекти директно в базата данни, а не само в паметта.

Типът NOT INSTANTIABLE не може да създава обекти директно; той действа като ABS.tracбаза, която други типове разширяват. В комбинация с NOT FINAL, той дефинира супертип, чиито подтипове осигуряват конкретната имплементация на декларираните му методи.

Използвайте ALTER TYPE, за да добавяте или премахвате атрибути и методи, добавете CASCADE, за да актуализирате зависими обекти, и използвайте DROP TYPE, за да премахвате типа. Тип, който все още се използва от таблици или други типове, не може да бъде премахнат, докато тези зависими обекти не бъдат обработени първо.

Извършете заявка към изгледите на речника с данни USER_TYPES и ALL_TYPES за имена на типове, и към USER_TYPE_ATTRS и USER_TYPE_METHODS за техните атрибути и методи. Тези изгледи ви позволяват да одитирате съществуващ обектен модел, без да четете изходния код.

Да. Копилот на GitHub създава спецификации на CREATE TYPE, методи на TYPE BODY, конструктори и функции на ORDER от коментар. RevПрегледайте типовете данни на атрибутите, параметрите на конструктора и клаузите за наследяване, преди да разгърнете генерирания тип.

Асистентите с изкуствен интелект анализират вашите таблици и предлагат типове обекти, карта на атрибутиpingи йерархии на наследяване. Този преглед на машинното обучение маркира излишни атрибути, липсващи конструктори и прекалено дълбоко наследяване, преди обектният модел да достигне производствения етап, подобрявайки поддръжката.

Обобщете тази публикация с: