Опубликован: 28.12.2011 | Доступ: свободный | Студентов: 7487 / 958 | Оценка: 3.81 / 3.53 | Длительность: 19:30:00
ISBN: 978-5-9963-0488-2
Лекция 11:

Объектные типы данных в Oracle

< Лекция 10 || Лекция 11: 1234 || Лекция 12 >
Ссылки на объекты

Благодаря наличию внутренних идентификаторов object ID у объектов из таблиц объектов и возможности на них ссылаться локализовать такие объекты становится возможным с применением не только обычной техники SQL, но и навигации с помощью ссылок.

Пример создания обычной таблицы со столбцом для ссылки на хранимый в таблице объектов (типа ADDRESS_TYPE) элемент-объект:

CREATE TABLE odept2 (
  dname    VARCHAR2 ( 50 )
, deptno   NUMBER CONSTRAINT pk_odept PRIMARY KEY
, addr     REF address_type SCOPE IS addresses1
);

Здесь описание ссылки сужено возможностью адресоваться только к объектам из таблицы ADDRESSES1. Допускаются варианты описания ссылки: ее нацеленность на содержимое конкретной таблицы можно не применять или же, напротив, усилить до аналогии со ссылочной целостностью (в этом примере аналогия с правилом внешнего ключа неполная).

Пример заполнения поля ADDR значением-ссылкой:

INSERT INTO odept2
   ( dname, deptno, addr )
VALUES
   ( 'RESEARCH', 10, ( SELECT REF ( a )
                       FROM addresses1 a
                       WHERE a.location = 'Archangelsk'
   )                 )
;

Пример допустимых оформлений обращения к свойствам объекта через ссылку:

COLUMN deref(d.addr) FORMAT A40
SELECT d.dname, DEREF ( d.addr ), d.addr.zip FROM odept2 d
;

Навигация по объектам в БД с помощью ссылок и в том числе извлечение объекта из БД возможны не только в запросах SQL, но и в программе на PL/SQL.

Пример использования методов объектов

Более сложные конструкции в описании типа позволяют задавать методы объектов и типов. Пример указания в типе метода:

CREATE TYPE employee_type AS OBJECT (
  name     VARCHAR2 ( 50 )
, hiredate DATE
, home     REF address_type
,
  MEMBER FUNCTION days_at_company RETURN NUMBER
)
/

Когда методов много, их заголовки перечисляются по очереди через запятую, общим списком со свойствами.

В описании типа приводится только заголовок методов. Для описания тела метода необходимо создать тело типа (полная аналогия пары пакет — тело пакета, имеющейся в PL/SQL):

CREATE TYPE BODY employee_type AS
MEMBER FUNCTION days_at_company RETURN NUMBER IS
   BEGIN
   RETURN TRUNC ( SYSDATE - hiredate );
   END;
END;
/

Пример использования типа в создании таблицы:

CREATE TABLE sailors ( ship VARCHAR2 ( 30 ), emp employee_type );
-- в этом контексте EMPLOYEE_TYPE — это имя типа

Использование конструктора типа для заполнения таблицы:

INSERT INTO sailors VALUES
   ( 'Ninna', employee_type ( 'Frank Naude', SYSDATE, NULL ) )
;
-- в этом контексте EMPLOYEE_TYPE — это конструктор

Использование свойств и метода типа для запроса к таблице:

COLUMN emp FORMAT a60
SELECT * FROM sailors;
SELECT x.ship, x.emp.name, x.emp.days_at_company ( ) FROM sailors x;
-- указание скобок после DAYS_AT_COMPANY сообщает, что это метод, а не свойство

Коллекции

Коллекции позволяют хранить в поле строки таблицы сразу множество значений: скалярных, объектов или ссылок на объект. Таким образом, в БД они представляют собой еще один способ группировки элементов, дополнительно к объектным таблицам. Oracle относит коллекции к объектным возможностям своей СУБД, и поэтому допускаются многоуровневые коллекции.

Формально коллекции определяются через тип, и поэтому явного нарушения скалярности данных в таблицах Oracle коллекции не создают: в столбце таблицы по-прежнему хранятся значения определенного типа. Однако содержательно они все-таки моделируют хранение набора величин как целого, и ввиду этого вызывают определенный скепсис со стороны знатоков реляционной модели.

Начиная с версии 8 в диалекте SQL Oracle имеется два вида коллекций: вложенные таблицы (неупорядоченное множество) и массивы VARRAY (упорядоченный список). Они соответствуют двум видам коллекций в стандарте SQL, но реализованы с некоторыми вольностями.

Вложеные таблицы

Вложеные таблицы (nested tables) в Oracle есть термин для обозначения возможности хранить в поле строки сразу множество значений ("таблицу" значений). Обычную таблицу в Oracle, некоторые столбцы которой описаны как "вложеные таблицы", всегда можно перепроектировать в информационно равносильный набор обычных таблиц с "единичными" столбцами.

Пример употребления вложеных таблиц:

CREATE TYPE colourset_typ AS TABLE OF VARCHAR2 ( 32 )
/
CREATE TABLE colour_models (
    model_type VARCHAR2 ( 12 )
  , colours    colourset_typ
)
NESTED TABLE colours STORE AS colour_model_colours_tab
-- фраза NESTED TABLE вынужденная, но может содержать указания оптимизации хранения
;
INSERT INTO colour_models VALUES (
  'RGB'
, colourset_typ ( 'RED', 'GREEN', 'BLUE' ) 
);
-- в этом контексте COLOURSET_TYP — конструктор коллекции
COLUMN colours FORMAT A60
SELECT * FROM colour_models
;

Пример приоткрывает то обстоятельство, что технически перечень самих значений из хранимых в столбце наборов располагается не непосредственно в основной таблице, а в отдельной вспомогательной (служебной), и ей мы обязаны дать по меньшей мере имя. Однако помимо этого во фразе NESTED TABLE при создании основной таблицы мы имеем право указать некоторые подробности организации доступа к этой служебной таблице и особенности хранения (например, табличное пространство).

< Лекция 10 || Лекция 11: 1234 || Лекция 12 >
Ярослав Прозоров
Ярослав Прозоров

В лекции № 7 "Введение в Oracle SQL" в подразделе "Несамостоятельность группировки с обобщениями ROLLUP, CUBE и GROUPING SETS"  представленная таблица сравнения содержит ошибки - окончания запросов пропущены. Видимо, ошибки вызваны некорректным переносом материала лекции.

Володимир Миколайчук
Володимир Миколайчук
Помогите разобраться поетапно с логикой запроса
-------TOOLS
NAME PRICE TYPE
drill 155 A
sawzall 192 N
mitre saw 292 M
router 86 I
RAD 145 M
jigsaw 128 I
screwdriver 77 P
------TOOL_TYPES
TYPE USAGE
A Always
I Often
M Sometimes
N Rarely
P Never

Запрос SQL:
SELECT t.type, SUM(t.price)
FROM tools t
GROUP BY t.type
HAVING SUM(t.price) >= (SELECT AVG(price)
FROM tools
WHERE type IN (SELECT type
FROM tool_types
WHERE usage = 'Often'));

И сколько строк он все таки вернет