Синергия
Большие объекты, определяемые пользователями типы и функции,
ограничения и триггеры представляют в отдельности мощные
возможности. Но истинная объектно-реляционная мощность DB2
происходит из синергии этих возможностей. В качестве примера
рассмотрим, как объектно-реляционные возможности DB2 могут быть
использованы на обеспечения хранения в базе данных
многоугольников.
Поскольку отсутствует предопределенный тип данных
"прямоугольник", то прежде всего нужно понять, каким образом
прямоугольники будут представляться в базе данных. Поскольку
прямоугольники потенциально могут быть довольно большими, мы
будем использовать для их представления тип больших объектов
BLOB. Но мы хотели бы отличить это представление от других
объектов типа BLOB и поэтому создадим индивидуальный тип POLYGON:
CREATE DISTINCT TYPE POLYGON AS
BLOB(1M);
Можно выбрать различные реальные представления многоугольников
внутри большого объекта. Например, это может быть
последовательность чисел, первое из которых задает число вершин
многоугольника, а следующие содержат координаты вершин.
После создания индивидуального типа желательное поведение
многоугольников может быть указано путем создания набора
соответствующих UDF. По крайней мере одна из этих функций должна
быть "конструктором", создающим многоугольник на основе более
простых типов, таких как POINT или DOUBLE. Работа
функции-конструктора состоит в упаковке примитивных частей
многоугольника в BLOB с последующим преобразованием типа BLOB к
типу POLYGON (для этого следует использовать сгенерированную
системой функцию преобразования типов POLYGON(BLOB).
Ниже перечислены некоторые из UDF, задающие поведение типа
POLYGON. Эти функции могут быть написаны, например, на языках Си
или Си++.
degree(Polygon) returns Integer;
area(Polygon) returns Double;
perimeter(Polygon) returns Double;
rotate(Polygon, Double) returns Polygon;
intersect(Polygon, Polygon) returns Polygon;
Теперь можно создавать таблицы со столбцами типа POLYGON.
Например, следующий оператор можно было бы использовать в
налоговом управлении для создания таблицы, в которой должны
регистрироваться земельные участки, находящиеся в частной
собственности:
CREATE TABLE properties
(taxid Char(6) PRIMARY KEY,
owner Varchar(32),
assessment Dollars,
parcel Polygon);
Для нахождения собственников больших участков можно использовать следующий запрос на языке SQL:
SELECT owner, area(parcel)
FROM properties
WHERE area(parcel) > 20000;
Наиболее эффективный способ выполнения этого запроса мог бы
базироваться на использовании индекса, обеспечивающего прямой
доступ к участкам по значению их площади. Поддержка индексов на
UDF находится в планах развития DB2, но пока ее нет. Но возможно
другое решение, позволяющее выполнить запрос с той же
эффективностью. Добавим к таблице PROPERTIES новый столбец,
который должен содержать заранее вычисленный размер площади, и
создадим триггеры для поддержки корректных значений этого
столбца. Для добавления столбца можно использовать оператор SQL
ALTER TABLE properties
ADD COLUMN area Double;
Теперь определим триггеры, которые активируются при выполнении
над таблицей PROPERTIES операторов INSERT и UPDATE. Вот как могло
бы выглядеть определение триггера для INSERT:
CREATE TRIGGER insertprop
NO CASCADE
BEFORE INSERT ON properties
REFERENCING NEW AS newrow
FOR EACH ROW MODE DB2SQL
SET newrow.area =
area(newrow.area);
Поскольку площадь каждого участка автоматически вычисляется и
хранится в отдельном столбце, для убыстрения доступа к участкам
по значению их площади можно создать индекс на столбце AREA:
CREATE INDEX proparea ON
properties(area);
Теперь перепишем запрос в форме, которая даст возможность DB2
использовать этот индекс:
SELECT owner, area
FROM properties
WHERE area > 20000;