How to keep edit history of large string field in relational database

后端 未结 2 1956
囚心锁ツ
囚心锁ツ 2021-02-20 06:10

N.B. I think answers are likely to be design-focused and therefore basically implementation agnostic, but I\'m using Java+Hibernate with Postgres if there\'s some particular

2条回答
  •  难免孤独
    2021-02-20 06:43

    I don't reply about storing diff or full changes even if in my opinion just a performance test can actually reply for what solution is better because full log of content means bigger database but less work for server.

    I want to share on the contrary, my experience for keep history with postgresql. I did it very successfully working on server site, just on postgresql without write any code out of it. Using this set of functions, triggers and extension on Postgresql

    http://andreas.scherbaum.la/blog/archives/100-Log-Table-Changes-in-PostgreSQL-with-tablelog.html

    They are simple and easy to implement and you can forget of history on your code but just you can read from the log table to present difference on the content.

    So my application was written in php with YII framework with db schemes and structure designed by me for data, with just few table as service for framework itself (users, roles and general log) and this is important because if the data structure in the db is too complicated the approach summarised below is still valid but more complicated.

    After installed the postgresql extension tablelog you find here http://pgfoundry.org/projects/tablelog/

    You can proceed this way: First you must select the table (mytable) with the content you need to keep history of. You duplicate this mytable (I did into a new schema log.mytable) adding some new columns to keep track of history (as describe into README into tablelog extension).

    You must create some simple functions on postgresl in pgplsql

    CREATE FUNCTION table_log ()
        RETURNS TRIGGER
        AS '$libdir/table_log' LANGUAGE 'C';
    CREATE FUNCTION "table_log_restore_table" (VARCHAR, VARCHAR, CHAR, CHAR, CHAR, TIMESTAMPTZ, CHAR, INT, INT)
        RETURNS VARCHAR
        AS '$libdir/table_log', 'table_log_restore_table' LANGUAGE 'C';
    CREATE FUNCTION "table_log_restore_table" (VARCHAR, VARCHAR, CHAR, CHAR, CHAR, TIMESTAMPTZ, CHAR, INT)
        RETURNS VARCHAR
        AS '$libdir/table_log', 'table_log_restore_table' LANGUAGE 'C';
    CREATE FUNCTION "table_log_restore_table" (VARCHAR, VARCHAR, CHAR, CHAR, CHAR, TIMESTAMPTZ, CHAR)
        RETURNS VARCHAR
        AS '$libdir/table_log', 'table_log_restore_table' LANGUAGE 'C';
    CREATE FUNCTION "table_log_restore_table" (VARCHAR, VARCHAR, CHAR, CHAR, CHAR, TIMESTAMPTZ)
        RETURNS VARCHAR
        AS '$libdir/table_log', 'table_log_restore_table' LANGUAGE 'C';
    

    Now you must create a trigger on your mytable as

    CREATE TRIGGER mytable_trg AFTER UPDATE OR INSERT OR DELETE ON mytable FOR EACH ROW EXECUTE PROCEDURE table_log('log.mytable');

    That's all, on every INSERT, UPDATE or DELETE you will keep track of history and you can easily restore old versions with the function you create before and so in your app code just executing and SQL calling the function itself.

    In my app I added an icon for History in several point where needed and with a click I open a dialog with form and a options in table to present all history and select the version you could restore.

    In the form creation, selecting content form log.mytable, you could place, in my opinion, a function that extract the difference from all version with the current but it's easy if you store the full content for every version in the db because on contrary it could be difficult to restore a version near to the last. In fact if you keep differences consider that they are compared with the next not with the current.

    Another advantage it that all is server side and no delay for writing extra data could be sensed on client side.

    The function for presenting just the difference mentioned below could also be a pgplsql function to avoiding, this way, to send to client all version in full content that could be big sometimes but this must depend on type of content, easily for text less for html and more complex for other type of content.

    My app was quite complex but keeping the history for changes this way has done a easy and clean and I forgot of it after done because always it worked smoothly.

    Luca

提交回复
热议问题