Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения
KANSoftWare

История изменений объектов

Delphi , Базы данных , База данных

История изменений объектов

Оформил: DeeCo

Автор: Виноградов С. А.

Введение

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

В качестве примера, возьмем таблицу Objects, которая содержит код объекта, его наименование, примечание и другие поля (здесь и далее — синтаксис MS SQL):

create table[Objects]
(
  [Id]int not null identity primary key,
  [Code]varchar(120) not null,
  [Name]varchar(120) not null,
  [Note]varchar(250),
  ...
  )

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


Дополнительная таблица истории

По многим соображениям, бывает необходимо оставить таблицу объектов на текущий момент в неизменном виде, а историю вести в отдельной таблице. Самый простой способ хранения истории — при любом изменении в объекте, добавлять в таблицу запись с новыми значениями объекта и приписывать к этой записи дату изменения. Тогда, структура таблиц Objects и ObjectsHistory будет примерно такой:

create table[Objects]
(
  [Id]int not null identity primary key,
  [Code]varchar(120) not null,
  [Name]varchar(120) not null,
  [Note]varchar(250),
  ...
  )

create table[ObjectsHistory]
(
  [object]int not null references[Objects]([Id]),
  [Code]varchar(120) not null,
  [Name]varchar(120) not null,
  [Note]varchar(250),
  ...
  [DateBegin]datetime not null default(getdate()),
  [DateEnd]datetime not null default('3000-01-01')
  constraint[ObjectHistory]primary key([object], [DateBegin])
  )

Первичный ключ в таблице истории состоит из двух полей: идентификатора объекта из основной таблицы (Object) и даты начала действия истории объекта (DateBegin). Дата окончания действия истории (DateEnd) всегда равна дате начала следующей истории объекта, и используется исключительно для более простых условий выборки.

При вставке записи в основную таблицу, необходимо добавить такую же запись в таблицу истории, где Object = идентификатор_объекта, DateBegin = текущая_дата, DateEnd = максимальная_дата.

При модификации записи в основной таблице, нужно вставить измененную запись в таблицу истории, где Object = идентификатор_объекта, DateBegin = текущая_дата, DateEnd = максимальная_дата. При этом у предыдущей записи с таким же идентификатором в таблице истории необходимо установить DateEnd = текущая_дата.

При удалении записи в основной таблице, у последней записи с таким же идентификатором в таблице истории надо установить DateEnd = текущая_дата.

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

Выборка из основной таблицы производится обычным образом, а из таблицы истории с условием:

заданная_дата beetwen DateBegin and DateEnd

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

Недостаток — повышенное дублирование информации (к примеру, последнее состояние будет одинаково в обеих таблицах) и, соответственно, большой объем базы данных.


Одна таблица для всех состояний

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

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

create table[Objects]
(
  [Id]int not null identity primary key
  )

create table[ObjectsHistory]
(
  [object]int not null references[Objects]([Id]),
  [Code]varchar(120) not null,
  [Name]varchar(120) not null,
  [Note]varchar(250),
  ...
  [DateBegin]datetime not null default(getdate()),
  [DateEnd]datetime not null default('3000-01-01')
  constraint[ObjectHistory]primary key([object], [DateBegin])
  )

Первичный ключ в таблице истории состоит из двух полей: идентификатора объекта из таблицы ключей (Object) и даты начала действия истории объекта (DateBegin). Дата окончания действия истории (DateEnd) равна дате начала следующей истории объекта, и используется для более простых условий выборки.

При вставке объекта, необходимо вначале добавить запись в таблицу ключей и получить идентификатор объекта. Затем надо произвести запись в таблицу истории, где Object = идентификатор_объекта, DateBegin = текущая_дата, DateEnd = максимальная_дата.

При модификации объекта, нужно вставить измененную запись в таблицу истории, где Object = идентификатор_объекта, DateBegin = текущая_дата, DateEnd = максимальная_дата. При этом, у предыдущей записи с таким же идентификатором необходимо установить DateEnd = текущая_дата.

При удалении объекта, для последней записи с таким же идентификатором надо установить DateEnd = текущая_дата.

Выборка последнего состояния объектов производится с условием:

текущая_дата beetwen DateBegin and DateEnd

Условие для выборки на определенную дату:

заданная_дата beetwen DateBegin and DateEnd

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

Недостатком будет более сложное получение текущего состояния. Информация по-прежнему остается избыточной — при изменении одного из свойств объекта, он копируется целиком.


Заключение

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

Статья История изменений объектов раздела Базы данных База данных может быть полезна для разработчиков на Delphi и FreePascal.


Комментарии и вопросы


Ваше мнение или вопрос к статье в виде простого текста (Tag <a href=... Disabled). Все комментарии модерируются, модератор оставляет за собой право удалить непонравившейся ему комментарий.

заголовок

e-mail

Ваше имя

Сообщение

Введите код




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



:: Главная :: База данных ::


реклама



©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru Rambler's Top100

Время компиляции файла: 2024-04-24 22:55:34
2024-04-26 04:34:58/0.0071151256561279/2