Я реализовал чистые рекордные данные изменения с помощью "тонкого" дизайна:
RecordID Table Column OldValue NewValue
-------- ----- ------ -------- --------
Вы не можете хотеть использовать "Таблицу" и "Столбец", а скорее "Объект" и "Свойство", и т.д, в зависимости от Вашего дизайна.
Это имеет преимущество гибкости и простоты, за счет скорости запроса - кластерные индексы на столбцах "Table" и "Column" могут ускорить запросы и фильтры. Но если Вы собираетесь быть просмотром журнала изменений онлайн часто за Таблицей или уровнем объектов, можно хотеть разработать что-то более плоское.
Править: несколько человек справедливо указали, что с этим решением Вы не могли сплотить массив изменений. Я забыл это в приведенной выше таблице - реализация, с которой я работал, также имел таблицу "Transaction" с датой и временем, пользователем и другой информацией и столбцом "TransactionID", таким образом, дизайн будет похож на это:
CHANGE LOG TABLE:
RecordID Table Column OldValue NewValue TransactionID
-------- ----- ------ -------- -------- -------------
TRANSACTION LOG TABLE:
TransactionID UserID TransactionDate
------------- ------ ---------------
Вы после механизма базы данных как это?
CREATE OR REPLACE TRIGGER history$yourTable
BEFORE UPDATE ON yourTable
FOR EACH ROW
BEGIN
INSERT INTO
history
VALUES
(
:old.field1,
:old.field2,
:old.field3,
:old.field4,
:old.field5,
:old.field6
);
END;
/
SHOW ERRORS TRIGGER history$yourTable
До не хранения большого количества дополнительных данных я не могу думать ни о каких хороших способах сделать это. Необходимо сохранить каждый пересмотр для наблюдения изменений.
Вот одно решение, которое я видел, хотя я не уверен, является ли это лучшее. Имейте первичный ключ, скажите id
который указывает на конкретный пересмотр. также имейте ticket_number
и revision_date
поля. ticket_number
не изменяется, когда Вы пересматриваете билет, но id
и revision_date
сделать. Затем в зависимости от контекста можно получить конкретный пересмотр или последний пересмотр конкретного билета, с помощью groupwise максимум.
Я сказал бы, создают некоторое событие, слушая класс, который Вы проверяете с помощью ping-запросов каждый раз, когда что-то происходит в Вашей системе и помещает описание события в базе данных.
Это должно сохранить основную who/what/where/when/what информацию.
сортировка той таблицы событий проекта должна получить Вас информация, которую Вы хотите.
Я сделал что-то вроде этого. У меня есть таблица под названием LoggableEntity, который содержит: идентификатор (PK).
Затем у меня есть таблица EntityLog, которая содержит информацию об изменениях, внесенных в loggableentity (запись): идентификатор (PK), EntityID (FK к LoggableEntity. Идентификатор), ChangedBy (имя пользователя, кто внес изменение), ChangedAt (smalldatetime, когда изменение произошло), Тип (перечисление: Создайте, Удалите, Обновление), Детали (поле заметки, содержащее, что изменилось - мог бы быть XML с сериализированными деталями).
Теперь каждая таблица (объект), что я хочу быть прослеженным, "получена" из таблицы LoggableEntity - что это означает, что, например, у Клиента есть FK к таблице LoggableEntity.
Теперь мой код DAL заботится о заполнении таблицы EntityLog каждый раз существует изменение, внесенное в клиентскую запись. Каждый раз, когда это видит, что класс объекта является loggableentity затем, это добавляет новую запись изменения в entitylog таблицу.
Таким образом, вот моя структура таблицы:
+------------------+ +------------------+
| LoggableEntity | | EntityLog |
| ---------------- | | ---------------- |
| (PK) ID | <--+ | (PK) ID |
+------------------+ +----- | (FK) LoggableID |
^ | ... |
| +------------------+
+------------------+
| Customer |
| ---------------- |
| (PK) ID |
| (FK) LoggableID |
| ... |
+------------------+
Одно возможное решение хранит копию билета в таблице истории с пользователем, который внес изменение.
Однако это будет хранить много дополнительных данных и требовать, чтобы большая обработка создала представление, что Trac показывает.