Предполагая, что вы хотите сохранить это на уровне приложения, я бы посоветовал использовать слой модели со свойствами для каждого поля для ведения журнала. Весь доступ к данным затем проходит через эту модель данных, что дает вам возможность добавить функциональность.
Пример activerecord (VBScript):
class cSomeEntity
public db ' link to a db wrapper
private id, dirty, loaded ' varous flags
private sub class_initialize
dirty = false
loaded = false
end sub
private sub class_terminate
if dirty then
db.execute("update some_table set some_field=? where id=?", array(p_some_field, id))
end if
end sub
public sub load_by_id(value)
dim rs
set rs = db.fetch_rs("select id, some_field from some_table where id=?", array(id))
id = rs("id")
p_some_field = rs("some_field")
loaded = true
end sub
private p_some_field
public property get some_field
some_field = p_some_field
end property
public property let some_field(value)
if not loaded then err.raise 1, , "Entity not yet initialized, call .load_by_id() first!"
if value <> p_some_field then
dirty = true
make_log_entry("some_value", p_some_field, value)
p_some_field = value
end if
end property
private sub make_log_entry(field, old_value, new_value)
db.execute("insert into audit_log (table, field, old_value, new_value) values (?, ?, ?, ?)", _
array("some_table", field, old_value, new_value))
end sub
end class
Может показаться немного раздутым, но он более гибкий, чем подход, основанный на триггерах. Например, вы можете легко реализовать проверки диапазона и тому подобное.
Во-вторых, когда вам нужно написать несколько классов сущностей, вы можете добавить много функций в класс делегата и использовать шаблон кода для написания свойства getter & setters.