Объектно-ориентированные системы.
§ Объектно-ориентированные идеи проникают в мир отношений.
- Отношение сохраняется в качестве фундаментальной абстракции
§ Объектно-ориентированные СУБД использует класс как фундаментальную абстракцию и рассматривает отношение как один из многих типов
Мотивировка.
§ Позволить СУБД работать со специальными типами данных: картами, сигналами, картинками и т. п., которые бы могли использовать для своей обработки собственные специальные методы
§ Поддержка специальных методов даже для обычных реляционных данных.
§ Поддержка более сложных структур, чем «плоские файлы».
План.
1. Рассмотреть основные идеи, сформулированные в SQL стандарте.
2. Использовать Oracle 8i/9i обозначения в тех случаях, когда они похожи.
3. Ввести некоторые новые концепции из Oracle.
- Подробнее в документе, помещенном на страничке курса (раздел Объектно-ориентированные возможности Oracle).
Типы определенные пользователем (ТОП).
SQL разрешает ТОП, играющие двоякую роль:
1. Они могут быть типами отношений, т. е. типами кортежей отношений.
§ Иногда называют строчным типом.
2. Они также могут быть типом атрибута в отношении.
Определение ТОП. Пример и синтаксис Oracle.
CREATE TYPE BarType AS OBJECT (
name CHAR(20) UNIQUE,
addr CHAR(20)
);
/
CREATE TYPE BeerType AS OBJECT (
name CHAR(20) UNIQUE,
manf CHAR(20)
);
/
CREATE TYPE MenuType AS OBJECT (
bar REF BarType,
beer REF BeerType,
price FLOAT
);
/
Замечания.
§ В Oracle определения типов должны заканчиваться слэшем, вызывающим компиляцию типа.
§ Стандарт SQL похож на Oracle, но OBJECT не используется после AS.
Создание таблиц.
Определения типов сами не создают таблиц.
§ Они используются вместо списка элементов в операторе CREATE TABLE.
Пример.
CREATE TABLE Bars OF BarType;
CREATE TABLE Beers OF BeerType;
CREATE TABLE Sells OF MenuType;
Значения ТОП - подход Oracle.
§ Каждый ТОП имеет конструктор типа с тем же именем.
§ Значением(ями) этого типа являются значения атрибутов (полей), включенных в конструктор.
Пример.
SELECT * FROM Bars
производит значение BarType('Joe''s Bar', 'Maple St.')
Доступ к атрибутам объектов - подход Oracle.
§ Оператор. (точка) работает как обычно.
§ Так если мы хотим получить название бара и адрес без конструктора, можно использовать:
SELECT bb. name, bb. addr FROM Bars bb;
§ Технически, использование алиасной переменной bb не является необходимым, но как мы увидим позже, в некоторых случаях без этого не обойтись. Использование алиаса должно быть хорошей привычкой.
§ Стандарт SQL: похожая идея, но атрибут рассматривается как метод-генератор и отмечается круглыми скобками bb. name().
Добавление (вставка) данных - подход Oracle.
Мы можем использовать стандартный INSERT в Oracle, но мы должны заключить («завернуть») вставляемый объект в его тип-конструктор.
Пример.
INSERT INTO Bars VALUES(
BarType('Joe''s Bar', 'Maple St.')
);
Стандарт SQL использует для доступа к атрибутам методы 2х типов, автоматически создаваемых вместе с ТОП: метод-чтение(generator) и метод-обновление(mutator). Оба имеет то же имя, что и атрибут, однако первый не имеет параметров, а второй получает в качестве параметра значение, которое замещает текущее значение атрибута. В нашем случае, для вставки кортежа необходима следующая PSM процедура
CREATE PROCEDURE InsertBar (
IN n CHAR(20),
IN a CHAR(20)
)
DECLARE newBar BarType;
BEGIN
SET newBar = BarType();
newBar. name(n);
newBar. addr(a);
INSERT INTO Bars
VALUES(newBar);
END;
Теперь, чтобы добавить тот же бар, что в предыдущем примере, необходимо вызвать процедуру
InsertBar('Joe''s Bar', 'Maple St.');
Другой способ – написать метод, ассоциированный с типом, который будет принимать в качестве параметров значения атрибутов, и возвращать в качестве значения объект, который можно вставить при помощи INSERT. Например,
INSERT INTO Bars VALUES(NewBar('Joe''s Bar', 'Maple St.'));
где NewBar() – такой метод. Подробнее см. книгу.
Типы для столбцов.
ТОП может быть также типом столбца (атрибута) отношения.
Пример(Oracle). Создадим тип адреса для использования в отношениях.
CREATE TYPE AddrType AS OBJECT (
street CHAR(30),
city CHAR(20),
zip INT
);
Теперь мы можем создать отношение Drinkers, включающее имя, адрес и любимое пиво. Пиво включается как объект, это денормализует отношение, но считается вполне допустимым.
CREATE TABLE Drinkers (
name CHAR(30),
addr AddrType,
favBeer BeerType
);
Необходимость использования алиасов.
Если необходим доступ к атрибуту с ТОП, необходимо использовать алиас для отношения, т. е.
SELECT favBeer. name FROM Drinker;
Не будет работать в Oracle. Также не будет работать:
SELECT Drinker. favBeer. name FROM Drinker;
Правильно: SELECT dd. favBeer. name FROM Drinker dd;
Ссылки.
§ ТОП может содержать ссылку. Если Т является ТОП, то
REF( T ) будет ссылочным типом на объект типа Т.
§ В отличие от ОО систем ссылки имеют значения, которые могут просматриваться в запросах.
Разыменование в SQL.
A -> B = атрибут B объекта, на который указывает ссылочная переменная А.
Пример. Найти сорта пива, предлагаемые в Joe’s Bar.
SELECT beer -> name
FROM Sells
WHERE bar -> name = 'Joe''s Bar';
Разыменование в Oracle.
Разыменование автоматическое с использованием .(точки).
Тот же пример в синтаксисе Oracle.
SELECT ss. beer. name
FROM Sells ss
WHERE ss. bar. name = 'Joe''s Bar';
Оператор Oracle DEREF.
Если мы хотим получить полностью весь объект BeerType, следующий запрос не будет работать т. к. ss. beer является ссылкой, и мы получим «мусор»
SELECT ss. beer
FROM Sells ss
WHERE ss. bar. name = 'Joe''s Bar';
Правильным будет запрос
SELECT DEREF(ss. beer)
FROM Sells ss
WHERE ss. bar. name = 'Joe''s Bar';
Методы.
Это реальная причина того, что объектно-реляционный подход не означает просто наличие вложенных структур в отношениях.
§ Будем следовать синтаксису Oracle.
§ Объявляется в операторе CREATE TYPE statement, определяется в операторе CREATE TYPE BODY.
§ Методы являются функциями или процедурами, в Oracle они определяются подобно другим PL/SQL процедурам или функциям.
§ Имеется специальная переменная-кортеж SELF, ссылающаяся на объект, к которому применяется метод.
Пример.
Добавим метод priceInYen к типу MenuType, и, следовательно, к отношению Sells.
CREATE TYPE MenuType AS OBJECT (
bar REF BarType,
beer REF BeerType,
price FLOAT,
MEMBER FUNCTION priceInYen(
rate IN FLOAT) RETURN FLOAT,
PRAGMA RESTRICT REFERENCES
(priceInYen, WNDS)
);
/
CREATE TYPE BODY MenuType AS
MEMBER FUNCTION
priceInYen(rate FLOAT)
RETURN FLOAT IS
BEGIN
RETURN rate * SELF. price;
END;
END;
/
CREATE TABLE Sells OF MenuType;
На заметку.
§ Прагма необходима для того, чтобы можно было использовать метод priceInYen в запросах.
- WNDS = база данных не изменяется (write no database state)
§ В объявлении аргументы процедуры/функции должны иметь режим IN, OUT, или IN OUT, также как PL/SQL процедуры.
- Однако режим не указывается в определении метода.
§ Многие методы не имеют аргументы, используя встроенную переменную-кортеж SELF.
- В этом случае скобки после имени функции опускаются.
§ Тело метода может иметь любое количество объявлений процедур/функций, разделенных запятыми.
Пример использования метода.
Имя метода указывается после точки, следующей за именем (или выражением) объекта, к которому применяется метод, за именем метода в скобках указываются параметры.
SELECT ss. beer. name, ss. priceInYen(120.0)
FROM Sells ss
WHERE ss. bar. name = 'Joe''s Bar';
Встроенные функции сравнения (SQL).
Для каждого ТОП мы можем определить 2 функции EQUAL и
LESSTHAN. Это позволит значениям этого ТОП участвовать в сравнениях WHERE использующих =, <=, и т. п., а также в сортировке при помощи ORDER-BY.
Методы упорядочения в Oracle.
Мы можем объявить один метод для типа в качестве метода упорядочения.
§ Определение этого метода должно возвращать значение <0, 0, >0, если SELF соответственно «меньше», «равен» или «больше» объекта, передаваемого как аргумент метода.
§ Будет использоваться в сравнениях WHERE и для ORDER BY.
Пример. Упорядочивать объекты BarType по имени name.
CREATE TYPE BarType AS OBJECT (
name CHAR(20) UNIQUE,
addr CHAR(20),
ORDER MEMBER FUNCTION before(
bar2 IN BarType) RETURN INT,
PRAGMA RESTRICT REFERENCES
(before, WNDS, RNDS, WNPS, RNPS)
);
/
CREATE TYPE BODY BarType AS
ORDER MEMBER FUNCTION
before(bar2 BarType)
RETURN INT IS
BEGIN
IF SELF. name < bar2.name
THEN RETURN -1;
ELSIF SELF. name = bar2.name
THEN RETURN 0;
ELSE RETURN 1;
END IF;
END;
END;
/
Дополнительные коды в прагме гарантируют, что при выполнении метода не будет читаться или изменяться состояние базы данных или «пакета».


