Oracle Типы объектов PL/SQL: CREATE TYPE с примерами
⚡ Умное резюме
Объектные типы в PL/SQL позволяют использовать объектно-ориентированное программирование. OracleОни позволяют моделировать реальные сущности с помощью атрибутов и методов. Они поддерживают конструкторы, наследование и сравнение на равенство, поэтому один тип на уровне схемы может хранить и обрабатывать структурированные данные.

Что такое тип объекта в PL/SQL?
Объектно-ориентированное программирование особенно хорошо подходит для создания многократно используемых компонентов и сложных приложений. Программы организуются вокруг «объектов», а не «действий»; то есть они предназначены для работы и взаимодействия со всем объектом целиком, а не с отдельным действием. Такой подход позволяет программисту заполнять и изменять детали на уровне объекта и сущности.
На рисунке ниже представлен пример типа объекта, в котором банковский счет рассматривается как сущность. Атрибуты объекта содержат значения — для банковского счета это номер счета, остаток на банковском счете и так далее, — в то время как методы объекта описывают действия, такие как расчет процентной ставки или формирование банковской выписки, каждое из которых требует выполнения определенного процесса.
In PL/SQLОбъектно-ориентированное программирование основано на объектных типах. Объектный тип может представлять любую реальную сущность. В разделах ниже рассматриваются объектные типы, их компоненты, а также способы их создания и использования.
Компоненты типов объектов
Объектный тип PL/SQL состоит в основном из двух компонентов.
- Атрибуты
- Члены/Методы
Атрибуты
Атрибуты — это столбцы или поля, в которых хранятся данные. Каждый атрибут сопоставляется с типом данных, определяющим тип обработки и хранения для этого атрибута. Атрибут может иметь любой допустимый тип. Тип данных 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; /
Объяснение синтаксиса:
- Приведённый выше синтаксис показывает объявление переменная в качестве типа объекта в декларативном разделе.
После объявления переменной как объекта в подпрограмме она атомарно равна 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', и значения атрибутов вставляются в таблицу. Затем блок фиксирует изменения. сделка.
Выход:
Имя сотрудника: РРР
Номер сотрудника: 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.
Наследование в типе объекта
Свойство наследования позволяет дочернему типу объекта получать доступ ко всем атрибутам и членам родительского типа объекта.
Вспомогательный тип объекта называется наследуемым типом объекта, а супертип объекта — родительским типом объекта. Приведенный ниже синтаксис показывает, как создавать родительские и наследуемые типы объектов. На скриншоте ниже показан синтаксис родительского (СУПЕР) типа, помеченный как 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>, . ); /
Объяснение синтаксиса:
- Приведённый выше синтаксис демонстрирует создание подтипа. Он содержит все члены и атрибуты родительского типа объекта.
Пример 1: В приведенном ниже примере мы используем свойство наследования для вставки записи с идентификатором менеджера '1002' в запись ('RRR', 1007, 20000). Выполнение программы осуществляется в следующих шагах.
- Шаг 1: Создайте тип SUPER.
- Шаг 2: Создайте подтип и тело.
- Шаг 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_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 меньше, чем другой экземпляр.
- Ноль указывает на то, что экземпляр объекта 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.


















