объекты какого типа позволяет хранить база данных

Объекты и концепции базы данных

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

Следующие разделы содержат краткую информацию об объектах и концепциях базы данных InterBase:

Таблицы (Tables)

Реляционные базы данных хранят все данные в таблицах. Таблица это структура, состоящая из множества неупорядоченных горизонтальных строк (rows), каждая из которых содержит одинаковое количество вертикальных столбцов (colums). Пересечение отдельной строки и столбца называеися полем (field), которое содержит специфическую информацию. Многие принципы работы реляционной базы данных взяты из определений отношений (relations) между таблицами.

Системные таблицы имеют такую же структуру, как и определенные пользователем таблицы и расположенны в той же самой базе. Так как метаданные, пользовательские таблицы, и данные все вместе расположены в одном и том же файле базы данных, каждая база данных является законченным модулем и может быть легко перенесена между различными машинами.

Системные таблицы могут быть изменены подобно любой другой таблице базы данных. Если вы не понимаете всех взаимосвязей между системными таблицами, то непосредственное изменение их может иметь негативный эффект на другие системные таблицы и разрушить вашу базу данных.

Столбцы (Columns)

Создание таблицы главным образом подразумевает определение столбцов таблицы. Главные атрибуты столбца включают:

Типы данных (Data types)

Данные сохранены в определенном формате, который называется типом данных (data type). Типы данных могут быть классифицированы по четырем категориям: числовые (numeric), символьные (character), даты (date) и BLOB. Числовые данные включают в себя все числа, начиная с целых вплоть до чисел двойной точности с плавающей точкой. Символьные данные содержат строки текста. Даты используются для хранения дат и времени.

В то время как числовые, символьные и даты являются стандартными типами данных, BLOB-тип заслуживает специального внимания.

Тип данных BLOB аналогичен последовательному файлу (flat file), BLOB данные могут быть сохранены в любом формате (к примеру, бинарном или ASCII). BLOB, однако, это не отдельный файл. BLOB данные хранятся в базе данных наряду со всеми другими данными. Так как BLOB столбцы часто содержат большие и переменные объемы данных, BLOB столбцы хранятся в отдельных сегментах.

InterBase не поддерживает непосредственно преобразование BLOB данных в другие форматы, но на некоторых платформах, BLOB фильтры могут транслировать BLOB данные из одного формата в другой.

Домены (Domains)

В добавление к явному определению типа данных столбцов, InterBase обеспечивает глобальные определения столбцов или домены (domains), на которых могут базироваться определения столбцов. Домен содержит информацию о тип данных, устанавливает атрибуты и ограничения целостности столбцов. В последующем при создании таблиц возможно использовать домены для определения столбцов.

Справочные ограничения целостности (Referential integrity constraints)

Например, таблица EMPLOYEE могла бы быть определена имеющей внешний ключ столбец DEPT_NO. Который определен в соответствии со столбцом номера отдела в таблице DEPARTMENT. Это гарантировало бы, что каждый служащий из таблицы EMPLOYEE связан с существующим отделом в таблице DEPARTMENT.

Индексы (Indexes)

Индексы это механизм для улучшения быстродействия поиска данных. Индекс определяет столбцы которые могут быть использованы для эффективного поиска и сортировки в таблице.

InterBase автоматически определят уникальные индексы для первичных и внешних ключей таблицы.

Виды (Views)

Вид (view) это виртуальная таблица, которая не сохранена физически в базе данных, но ведет себя точно также как «реальная» таблица. Вид может содержать данные из одной или более таблиц или других видов и используется для хранения часто используемых запросов (queries) или множества запросов в базе данных.

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

Сохраненные процедуры (Stored procedures)

Сохраненные процедуры (stored procedure) это отдельные программы, написанные на языке процедур и триггеров InterBase, который является расширением SQL. Сохраненные процедуры являются частью метаданных базы данных. Сохраненные процедуры могут получать входные параметры, возвращать значения приложению и могут быть вызваны явно из приложения или подстановкой вместо имени таблицы в инструкции SELECT.

Сохраненные процедуры обеспечивают следующие возможности:

Триггеры (Triggers)

Триггеры это отдельная программа, ассоциированная с таблицей или видом, которая автоматически выполняет действия, при добавлений, изменений или удалений строки в таблице или виде.

Триггеры могут обеспечивать следующие возможности:

Когда триггер вызван, он имеет непосредвенный доступ к добавлению, изменению или уничтожению данных. Триггеру могут быть так же доступны данные из других таблиц. Вы можете разрабатывать триггеры для:

Генераторы (Generators)

Генератор (generator) это механизм который создает последовательный уникальный номер, который автоматически вставляется в столбец базой данных, когда выполняются операции INSERT или UPDATE. Генератор обычно применяется для создания уникальных значений, вставляемых в столбец, который используется как PRIMARY KEY. Для базы данных может быть определено любое число генераторов, каждый генератор должен имеет уникальное имя.

Защита (Security)

Источник

База данных — хранилище объектов

Классической методикой проектирования баз данных (БД) является создание отдельной таблицы для каждой описываемой моделью данных сущности, затем — в процессе нормализации — выделение отдельных таблиц для хранения атрибутов сущности (таблицы-справочники). Такой подход хорошо работает для БД с относительно небольшим количеством описываемых объектов (десятки) и при несложных и статичных связях между ними. Однако любое изменение структуры хранимых данных приводит к внесению изменений в структуру таблиц, эти данные отображающих. Несложная на этапе разработки, эта операция становится крайне проблематичной при больших объемах данных и при отсутствии у разработчика непосредственного доступа к БД (например, если она находится у заказчика). Многим, наверное, знакомы громоздкие, медленные и требующие огромного дискового пространства операции по конвертированию БД при переходе на новую версию продукта. Не менее неприятна работа с БД, исторически разросшейся до сотен таблиц, структуру которой сложно даже изобразить в читабельном виде. В связи с этим встает вопрос: а нельзя ли создать структуру данных, не требующую переделок при появлении новых сущностей и позволяющую хранить произвольную и при этом достаточно простую и эффективную информацию? Чудес, увы, не бывает. Любая универсальная система менее эффективна, чем специализированная. Однако возможно создание решения, в котором бы приемлемая производительность и простота сочетались с достаточной степенью универсальности.

Читайте также:  962825 какой оператор и регион город

Базовые тезисы

Прежде всего необходимо сформулировать основные принципы, на которых будет строиться проектируемая БД.

Такая БД не привязана ни к какой бизнес-модели и позволяет реализовать «над собой» практически любую бизнес-логику. Логика выделяется в отдельный программный слой и, как правило, реализуется на сервере приложений, где по запросу клиента создаются объекты, загружающие информацию о себе из БД и реализующие «поведение» объектов реального мира. В то же время, в силу однообразности модели хранения, эти объекты довольно легко создаются на основе базовых классов, инкапсулирующих функциональность по загрузке и сохранению свойств и связей в БД.

Объекты

Объект в нашей БД — понятие скорее логическое, его основное назначение — предоставить уникальный идентификатор, по которому его можно будет отличить. Кроме того, каждый объект обладает типом. Типы описываются таблицей:

ObjType
Id INTEGER Первичный ключ
Code CHAR(10) NOT NULL UNIQUE Краткое название типа. Используется в программе для поиска объектов данного типа
ItemName CHAR(30) Полное название типа, используется только для интерфейса

Типами объектов могут быть, например, «Фирма», «Сотрудник», «Товар».

Для упрощения не будем реализовывать наследования — отметим лишь, что для этого необходимо ввести в ObjType поле ParentId, ссылающееся на Id наследника.

Сами объекты хранятся в таблице:

Objects
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES ObjType(Id) Ссылка на тип объекта
ItemName CHAR(50) Название объекта

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

Таким образом, мы получаем возможность хранить объекты произвольного количества типов. Выборка объектов конкретного типа производится запросом вида

Однако наименования явно недостаточно для описания произвольного объекта из реального мира. Поэтому дополним создаваемую БД группой таблиц для описания свойств объектов.

Свойства

Свойства объектов отражают реальные атрибуты описываемых ими сущностей. Все они принадлежат к какому-то объекту и содержат некую информацию об атрибуте и его величине, причем список атрибутов является общим для всех объектов одного и того же типа.

Величина же может выражаться данными различного типа. Будем хранить в БД атрибуты следующих типов:

Строковые атрибуты

Для описания атрибутов заведем таблицу

StrDesc
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES ObjType(Id) Ссылка на тип объекта
Code CHAR(10) Краткое название параметра
ItemName CHAR(30) Полное название параметра, используется только для интерфейса

При настройке БД для каждого типа объектов задается набор свойств данного типа. Так, например, объект типа «EMPLOYEE» (Сотрудник) может иметь строковые свойства:

«EMAIL» — адрес электронной почты

Поле Objects.ItemName для сотрудников заполняется сервером приложений как комбинация из атрибутов FAMILY + FIRSTNAME + LASTNAME.

Сами атрибуты хранятся в таблице:

Strings
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES StrDesc(Id) Ссылка на тип параметра
ObjectId INTEGER REFERENCES Objects(Id) Ссылка на объект
Value VARCHAR(255) Значение параметра

Чтобы получить список сотрудников, имеющих E-mail, можно использовать запрос:

Для получения списка всех сотрудников с указанием адресов электронной почты для тех, у кого они есть, запрос надо модифицировать:

Интересный эффект можно получить, создав у различных типов объектов атрибуты с одинаковыми значениями поля Code. Предположим, что у объектов типов EMPLOYEE (сотрудник) и FIRM (организация) есть строковые атрибуты с одинаковым именем ‘EMAIL’. Тогда можно одним запросом получить адресную книгу по всем известным в БД почтовым адресам.

Если впоследствии добавится новый объект с аналогичным атрибутом, его наличие будет немедленно учтено и он появится в списке без каких-либо модификаций БД и запросов. Добиться подобного результата в БД с традиционной структурой будет как минимум сложно.

Числовые атрибуты

Для простоты будем предполагать, что для хранения любых числовых атрибутов достаточно одного типа данных, например DECIMAL(20,4). В серверах, поддерживающих тип MONEY, удобно реализовывать хранение на базе этого типа. Если же логика БД требует выделения отдельного целого либо другого типа данных — это можно сделать путем выделения для него отдельной группы таблиц. В остальном хранение значений этого типа аналогично строковым. Описание атрибутов хранится в таблице:

PropDesc
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES ObjType(Id) Ссылка на тип объекта
Code CHAR(10) Краткое название параметра
ItemName CHAR(30) Полное название параметра, используется только для интерфейса

А сами атрибуты — в таблице:

Properties
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES PropDesc(Id) Ссылка на тип параметра
ObjectId INTEGER REFERENCES Objects(Id) Ссылка на объект
Value DECIMAL(20,4) Значение параметра. На серверах, поддерживающих тип данных MONEY (аналог Currency в Delphi), удобно использовать этот тип

При необходимости возможно пополнить таблицу PropDesc дополнительными полями, задающими минимальное и максимальное значение атрибута, значение по умолчанию и т.п. Проверка корректности этих значений может осуществляться в триггере на изменение таблицы Properties.

Исторические атрибуты

Многие объекты в процессе своей «жизни» изменяют свое состояние. Так, сотрудник может быть принят на работу, уволен, снова принят, товар оприходован и продан и т.д. Для описания состояний объекта служит таблица:

Status
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES ObjType(Id) Ссылка на тип объекта
Code CHAR(10) Краткое название состояния
ItemName CHAR(30) Полное название состояния, используется только для интерфейса

Например, для человека допустимые состояния могут включать:

«WASBORN» — Дата рождения

«EMPLOYEED» — Принят на работу

При этом возможно реализовать логику, когда любое состояние может возникать многократно, например человек может быть принят, уволен, потом снова принят и т.п.

Сама история состояний хранится в таблице:

History
Id INTEGER Первичный ключ
StatusId INTEGER REFERENCES Status(Id) Ссылка на тип состояния
ObjectId INTEGER REFERENCES Objects(Id) Ссылка на объект
ItemDate DATETIME Дата возникновения состояния

При изменении состояния объекта в History добавляется запись со ссылкой на это состояние и датой его возникновения. Например, при увольнении сотрудника в его историю состояний добавляется запись с датой увольнения и ссылкой на состояние «DISMISS». Если этот же человек снова принят на работу — достаточно добавить новую запись с датой приема и ссылкой на состояние «EMPLOYEED». Список сотрудников, числящихся на работе на любую интересующую дату, может быть получен запросом вида:

Читайте также:  в какое время суток лучше принимать простамол уно мужчинам

Перечислимые атрибуты

Последним видом атрибутов будут перечислимые типы, которые могут принимать одно из заранее заданного набора значений. Для этих данных нам понадобится не две, как для остальных, а три таблицы. Первая из них задает перечисления, допустимые для выбранного типа объекта:

EnumDesc
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES ObjType(Id) Ссылка на тип объекта
Code CHAR(10) Краткое название состояния
ItemName CHAR(30) Полное название состояния, используется только для интерфейса

Вторая — определяет возможные значения для перечислимого типа:

EnumValues
Id INTEGER Первичный ключ
DescId INTEGER REFERENCES EnumDesc(Id) Ссылка на тип перечисления
Code CHAR(10) Краткое название значения
ItemName CHAR(30) Полное название значения, используется только для интерфейса

Третья — непосредственно хранит значения, связанные с объектом:

Enums
Id INTEGER Первичный ключ
ValueId INTEGER REFERENCES EnumValues(Id) Ссылка на значение
ObjectId INTEGER REFERENCES Objects(Id) Ссылка на объект

Типичным примером использования этого типа данных является форма собственности фирмы. Для ее определения необходимо вставить в EnumDesc строку:

TypeId Code ItemName
Ссылка на ObjType для типа «FIRM» OWNERFORM Форма собственности
DescId Code ItemName
Ссылка на EnumDesc для ИЧП Индивидуальное частное предприятие
типа «OWNERFORM» ООО Общество с ограниченной ответственностью
.

Таким образом, мы получили возможность описать произвольный набор свойств любой сущности, данные о которой хранятся в БД, и отобразить ее на единообразно хранимые объекты. Однако на настоящий момент база данных еще не пригодна для решения сколь-нибудь сложных задач, поскольку реальные объекты любой предметной области имеют друг с другом разнообразные связи, которые пока не может отразить наша БД.

Связи

Сущности реального мира имеют между собой множество различных связей, определяющих их роль и место в этом мире. В традиционной методологии построения БД связи отображаются на ссылки (REFERENCES) между таблицами, в которых хранится описание соответствующих сущностей. Такой подход обеспечивает высокую эффективность БД и возможность автоматической проверки и поддержания целостности связей (механизмы referential integrity), однако жестко ограничивает связи, хранимые в БД ее структурой. В нашей структуре данных не предусмотрено отдельных полей для хранения ссылок на другие таблицы. Вместо них в БД вводятся дополнительные таблицы.

Первая из них описывает возможные типы связей, которые могут быть установлены между объектами:

LinkType
Id INTEGER Первичный ключ
Code CHAR(10) Краткое название связи
ItemName CHAR(30) Полное название связи, используется только для интерфейса

Например, сотрудник может быть связан с отделом, в котором он работает, связью типа «EMPDEPART» (сотрудник в отделе). В то же время он может быть связан с отделом связью «BOSS» (начальник отдела). Со сторонней фирмой сотрудник может быть связан как менеджер, а с документом — как его создатель. Сами связи хранятся в таблице:

Links
Id INTEGER Первичный ключ
ParentId INTEGER REFERENCES Objects(Id) Ссылка на первый из связываемых объектов
ChildId INTEGER REFERENCES Objects(Id) Ссылка на второй из связываемых объектов
TypeId INTEGER REFERENCES LinkType(Id) Ссылка на тип связи

Таким образом, чтобы найти менеджера, прикрепленного к фирме, необходимо выполнить запрос:

А всех сотрудников отдела поставок можно найти запросом:

Опытные разработчики, видимо, уже заметили слабость предлагаемой схемы — связи никак не контролируются и ничто не гарантирует, что «сотрудником» отдела не окажется счет-фактура. Поскольку описание связей между объектами является «сердцем» разрабатываемой БД, необходимо ввести в нее механизм, контролирующий допустимость устанавливаемой связи. Таким механизмом служит таблица допустимых связей:

AllowedLinks
Id INTEGER Первичный ключ
ParentId INTEGER REFERENCES ObjType(Id) Ссылка на тип первого из связываемых объектов
ChildId INTEGER REFERENCES ObjType(Id) Ссылка на тип второго из связываемых объектов
TypeId INTEGER REFERENCES LinkType(Id) Ссылка на тип связи

На вставку и изменение записей в Links создается несложный триггер, который проверяет типы объектов для создаваемой связи и их допустимость по AllowedLinks. Поскольку разрешенные типы связей хранятся в таблице, мы получаем гибкий механизм для настройки БД под требования конкретной задачи. Если требуется задать новый тип связи между объектами — достаточно лишь добавить в AllowedLinks запись с этим типом связи и типами объектов.

Замечу, что предлагаемая модель позволяет легко хранить иерархические данные. Для этого надо лишь задать связь типа «находится в».

Выбирая, какой тип объекта должен быть первым (ParentId), а какой вторым (ChildId) в связи, рекомендуется придерживаться единой системы. Для БД это безразлично, однако для уменьшения путаницы лучше в качестве первого выбирать объект, который бы оказался на стороне «один» отношения «один-ко-многим» при проектировании БД по классической методике. Если объекты связаны по принципу «многие-ко-многим», надо просто выработать для себя единую методику и в дальнейшем ей следовать.

Расширение БД

Итак, полученная БД может хранить описание произвольных сущностей, позволяет динамически определять и устанавливать между ними произвольные связи. Для многих задач (например, отдел кадров), в которых каждый объект уникален, этого уже достаточно. Однако существует много задач, под которые полученное «ядро» было бы неплохо пополнить дополнительными возможностями.

Налаживаем учет

Существует большой класс объектов, экземпляры которых с точки зрения учета не отличаются друг от друга. К таким объектам применимо понятие количества. Например, нам безразлично, какие конкретно рубли лежат в кассе. Важно лишь знать, СКОЛЬКО их там. Подобные объекты широко распространены в задачах учета материальных ценностей. Задачи учета требуют хранения в БД информации о перемещениях материальных ценностей и их остатках. Отметим, что остатки есть расчетная величина, которая может быть легко рассчитана из перемещений. Таким образом, хранение остатков может осуществляться в целях кэширования часто требующейся информации и его методика определяется скорее особенностями реализуемой системы. Зачастую от учета можно вообще отказаться и пересчитывать остатки «на лету», по мере поступления запросов от пользователей.

Для хранения информации о перемещениях заведем таблицу:

Movement
Id INTEGER Первичный ключ
OperationId INTEGER REFERENCES Objects(Id) Ссылка на объект-операцию, группирующую логически связанные перемещения
ContainerId INTEGER REFERENCES Objects(Id) Ссылка на объект-хранилище, на который совершается приход либо с которого совершается расход
ContentId INTEGER REFERENCES Objects(Id) Ссылка на объект, который перемещается
Amount DECIMAL(20,4) Количество
ItemDate DATETIME Дата перемещения

Рассмотрим некоторые поля этой таблицы подробнее.

OperationId

Каждая операция может состоять из нескольких перемещений. Например, расход товара со склада и приход его на фирму-покупателя. Чтобы иметь возможность логически связать эти перемещения, их группируют в операцию. В то же время операция часто имеет ряд дополнительных атрибутов (менеджер, срок выполнения, тип) и т.п. Поэтому — объявим операцию объектом и будем хранить информацию о ней наравне с другими объектами БД. Можно завести отдельные типы объектов для различных операций, диктуемых предметной областью. Наша схема позволяет легко определить такие виды операций, как:

ContainerId

Ссылка на объект-хранилище, на который приходят либо с которого уходят материальные ценности. Таким объектом может быть склад, касса, фирма-контрагент и т.п. Хранилище само может выступать как перемещаемый объект — например гвозди лежат в ящике, а ящик лежит на складе.

Читайте также:  обхват бедер 123 какой размер

Amount

Перемещаемое количество. Если Amount > 0 — это приход, в противном случае — расход.

Поскольку все операции однообразно хранятся в одной таблице, появляются богатые возможности по ведению аналитики. Например, остатки денег в кассе на любую дату можно получить с помощью несложного запроса

вернет суммы прихода на склад по всем товарам (тип объекта «GOOD») за период от StartDate до EndDate.

Истинная мощь аналитических возможностей становится понятной, если вспомнить о богатых возможностях группировки объектов по связям между ними (Links).

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

AllowedMovement
Id INTEGER Первичный ключ
ContainerId INTEGER REFERENCES ObjType(Id) Ссылка на тип объекта-хранилища
ContentId INTEGER REFERENCES ObjType(Id) Ссылка на тип перемещаемого объекта

Триггер на таблицу Movement не допускает создания записей с недопустимыми (то есть отсутствующими в AllowedMovement) типами объектов.

Под ценой мы будем понимать некоторый курс, по которому один объект может быть обменен на другой. Так, ценой может являться курс обмена валюты или отпускная цена. При этом для каждого объекта может существовать много цен (цена оприходования, отпускная и т.п.). Для хранения типов цен добавим в БД таблицу:

PriceType
Id INTEGER Первичный ключ
Code CHAR(10) Краткое название типа цены
ItemName CHAR(30) Полное название типа цены, используется только для интерфейса

Сами цены будем хранить в таблице:

Price
Id INTEGER Первичный ключ
TypeId INTEGER REFERENCES PriceType(Id) Ссылка на тип цены
WhereId INTEGER REFERENCES Objects(Id) Ссылка на объект, по которому установлена цена. Это может быть наша фирма, участок обмена валюты, валютная биржа, фирма-контрагент и т.п.
ObjectId INTEGER REFERENCES Objects(Id) Ссылка на объект, цена которого устанавливается данной записью
CurrencyId INTEGER REFERENCES Objects(Id) Ссылка на объект, в единицах которого выражена цена
Value DECIMAL(20,4) Цена
PriceDate DATETIME Дата, начиная с которой действует цена

Таким образом, мы можем задать любое количество цен по любому объекту. Например, товар по оприходованию получает входную цену, затем ему назначается долларовая цена, а впоследствии, время от времени, начиная с каких-то дат — рублевая. Каждая из подсистем учета (бухгалтерия, торговый зал и т.п.) может выбирать и работать с интересующими их ценами. Для ведения курсов валют достаточно завести объекты, устанавливающие эти курсы и по ним вести цену типа «EXCHANGE» (курс обмена) по интересующим валютам.

Проблемы и пути их решения

При построении БД мы пошли на ряд очень серьезных компромиссов, обеспечивших нам чрезвычайную гибкость и настраиваемость подсистемы хранения. Разработчику полезно знать возникающие при этом проблемы, чтобы иметь возможность учесть их при использовании подобной системы.

Ослабленный контроль за целостностью данных

Разбив данные об одном объекте по нескольким таблицам, мы теряем возможность на декларативном уровне контролировать правильность ввода данных. Так, нельзя указать серверу не позволять вводить объект при незаполненном атрибуте либо при неуказанной связи с другим объектом. Таким образом, на разработчика и администратора ложится дополнительная работа по программированию проверки ограничений и по недопущению прямой работы пользователей с БД. Задача эта хорошо решается путем создания сервера приложений, через который осуществляется доступ к данным. При отсутствии такой возможности рекомендуется манипуляции с объектами вынести в хранимые процедуры, лишив пользователей БД права модифицировать таблицы напрямую.

При необходимости возможно дополнение таблиц, хранящих описание атрибутов (StringDesc, PropDesc и т.п.) полями, несущими информацию об ограничении значений вводимого атрибута. Например, можно добавить в таблицу PropDesc поля MinValue и MaxValue и в триггере на таблицу Properties проверять соответствие вводимых значений заданному диапазону. Подобные расширения зависят от конкретной реализации всей системы и здесь для простоты не рассматривались, однако разработчик имеет возможность применить их про необходимости.

Пониженное быстродействие при выборке данных

Хранение атрибутов в различных таблицах требует аккуратности при программировании выборки множества объектов. Так, чтобы получить одновременно несколько атрибутов, придется написать запрос вида:

Кроме неудобства в написании (об этом мы поговорим позже), такой запрос может привести еще и к медленному выполнению на сервере. Выходом из ситуации может послужить автоматическое формирование в поле Objects.ItemName краткого описания объекта, необходимого для поиска его в списке себе подобных и использование преимущественно этого поля. Прочие атрибуты, выводимые в список объектов, должны по возможности исключаться из него. Как правило, это условие вполне выполнимо. Практика показывает, что вывод имени объекта и двух-трех атрибутов вполне достаточен для его выбора и практически не создает проблем для сервера.

Сложность в понимании структуры и выборке данных

Структура БД, не ориентированная на бизнес-логику, часто бывает затруднительной для понимания. Часто даже достаточно квалифицированным разработчикам требуется некоторое время, чтобы понять принципы хранения объектов и связи между ними. Еще хуже обстоит дело с конечными пользователями, которым бывает нужен нестандартный доступ к хранящейся в БД информации для ее анализа. Преодолением данной проблемы может послужить создание набора представлений (VIEW), предоставляющих более простой доступ к данным. Так, создав следующие представления:

мы сможем записать запрос из предыдущего раздела как:

Очевидно, что такой запрос уже гораздо проще воспринимается неподготовленным человеком. Также можно создать представления для различных типов объектов с набором наиболее употребимых их атрибутов.

Построение клиентской части

В роли клиентской части для такой БД, как правило, выступает сервер приложений, реализующий слой бизнес-логики. Для его создания реализуется иерархия классов

В TBaseDBObject реализуется базовая функциональность по загрузке свойств из БД и сохранению их в БД, а также интерфейсные методы, позволяющие ему общаться со слоем представления данных, расположенным на клиентской машине. Наследники создаются для каждого типа объектов в БД и реализуют логику их поведения. Возможна реализация этих объектов как COM-серверов, скомпилированных в отдельные DLL и подключаемых к основному модулю сервера приложений при необходимости (либо, например, как объектов Microsoft Transaction Server). eye

При построении интерфейса пользователя удобно реализовать набор базовых классов, умеющих работать с информацией о произвольном объекте БД. Такие классы, оформленные в виде компонентов, позволяют легко компоновать интерфейсные решения для работы с конкретными типами объектов. На рисунке приведены два таких компонента: наследник TListBox, отображающий информацию о свойствах объекта, и наследник TTreeView, отображающий другие объекты, связанные с выбранным, и типы связей. Оба они реализованы независимыми от типа конкретного объекта, за счет единообразия хранения информации о свойствах и связях. Такая пара компонентов позволяет легко реализовать произвольное перемещение по связям между объектами в БД, что достаточно сложно реализуется в традиционной БД.

Источник

admin
Своими руками
Adblock
detector