Сужение с TREAT
Oracle предоставляет специальную функцию TREAT, которая позволяет выполнять операцию сужения. Функция TREAT явно изменяет объявленный тип источника в присваивании на более специализированный тип или подтип в иерархии места назначения.
Для успешного сужения нужно использовать TREAT; без использования этой функции, вы не сможете сослаться на специфичные для подтипа атрибуты и методы.
Вот общий синтаксис этой функции:
TREAT (<object instance> AS <object type>)
где <object instance> - это значение столбца или строки коллекции данного конкретного супертипа в объектной иерархии, а <object type> - это подтип в этой иерархии.
Давайте рассмотрим несколько примеров использования TREAT. Предположим, что я вставил три строки в таблицу meal, как показано в Листинге 3. Обратите внимание, что в третьей строке я передал десерт в качестве главного блюда, одно из любимых занятий моего сына во время еды! Я смог сделать это, поскольку не ограничил подставляемость столбца main_course.
Предположим, что я хочу видеть список всех приемов пищи, в которых десерт указан в качестве главного блюда. Я использую оператор TREAT в предложении WHERE:
Функция TREAT - которую, кстати, в Oracle9i версии 1 можно использовать только в операторах SQL (но не в PL/SQL блоках) - возвращает объектный тип NULL для любых главных блюд, не являющихся десертами.
Допустим, я хочу узнать, содержит ли какое-нибудь из моих главных блюд шоколад. Этот атрибут характерен для десертов, поэтому если я попытаюсь напрямую сослаться на этот атрибут без TREAT, мой запрос завершится с ошибкой, как показано ниже:
SQL> SELECT main_course.contains_chocolate 2 FROM meal 3 WHERE TREAT (main_course AS dessert_t) 4 IS NOT NULL; SELECT main_course.contains_chocolate * ERROR at line 1: ORA-00904: invalid column name
Даже если все выбранные главные блюда являются десертами, у Oracle нет возможности узнать это; столбец main_course объявлен как тип food_t. Итак, что я должен делать? Использовать функцию TREAT в списке SELECT также как в запросе! Этот запрос и результаты представлены в Листинге 4.
Я могу также использовать TREAT в DML операциях, таких как INSERT'ы и UPDATE'ы. Предположим, например, что я не хочу разрешать вставлять в таблицу meal такие строки, в которых десерт является основным блюдом. Я могу добавить ограничение на таблицу, чтобы предотвратить это, но я также могу удалить все такие строки, используя UPDATE вместе с TREAT.
Только помните, что мы пока не можем использовать TREAT вне SQL оператора, напрямую в родном PL/SQL коде. Возможно, мы получим PL/SQL TREAT в Oracle9i версии 2.