I've done something for this in an Oracle database trigger, but I the same approach can be done in Perl if you want to be database agnostic. I set up an audit table with columns like table_name, primary_key (assumes a single column key, but could be modified for compound keys), value_before, value_after, user_name and date_changed. Every time a DML statement is performed, a row is inserted in the database for each column affected in that statement. Naturally, inserts will have no before values, and deletes will have no after values