Синергия
Большие объекты, определяемые пользователями типы и функции, ограничения и триггеры представляют в отдельности мощные возможности. Но истинная объектно-реляционная мощность DB 2 происходит из синергии этих возможностей. В качестве примера рассмотрим, как объектно-реляционные возможности DB 2 могут быть использованы на обеспечения хранения в базе данных многоугольников.
Поскольку отсутствует предопределенный тип данных “многоугольник”, то прежде всего нужно понять, каким образом многоугольники будут представляться в базе данных. Поскольку многоугольники потенциально могут быть довольно большими, для их представления должен использоваться тип больших объектов BLOB . Но хотелось бы отличить это представление от других объектов типа BLOB , и поэтому мы создадим индивидуальный тип POLYGON :
CREATE DISTINCT TYPE POLYGON AS BLOB(1M);
Можно выбрать различные реальные представления многоугольников внутри большого объекта. Например, это может быть последовательность чисел, первое из которых задает число вершин многоугольника, а следующие содержат координаты вершин. После создания индивидуального типа желательное поведение многоугольников может быть указано путем создания набора соответствующих UDF . По крайней мере, одна из этих функций должна быть “конструктором”, создающим многоугольник на основе более простых типов, таких как POINT или DOUBLE . Работа функции-конструктора состоит в упаковке примитивных частей многоугольника в BLOB с последующим преобразованием типа BLOB к типу POLYGON (для этого следует использовать сгенерированную системой функцию преобразования типов POLYGON ( BLOB )) . Ниже перечислены некоторые из UDF , задающие поведение типа POLYGON . Эти функции могут быть написаны, например, на языках C или C ++.
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 находится в планах развития DB 2, но пока ее нет. Но возможно другое решение, позволяющее выполнить запрос с той же эффективностью. Добавим к таблице 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);
Теперь перепишем запрос в форме, которая даст возможность DB 2 использовать этот индекс:
SELECT owner, area
FROM properties
WHERE area > 20000;