“Diffing” objects from a relational database

后端 未结 12 1227
遇见更好的自我
遇见更好的自我 2021-02-04 15:05

Our win32 application assembles objects from the data in a number of tables in a MySQL relational database. Of such an object, multiple revisions are stored in the database.

12条回答
  •  孤独总比滥情好
    2021-02-04 15:18

    In your situation in PostgreSQL I used a difference tables with the schema:

    history_columns (
        column_id smallint primary key,
        column_name text not null,
        table_name text not null,
        unique (table_name, column_name)
    );
    create temporary sequence column_id_seq;
    insert into history_columns
    select nextval('column_id_seq'), column_name, table_name
        from information_schema.columns
        where
            table_name in ('table1','table2','table3')
            and table_schema=current_schema() and table_catalog=current_database();
    
    create table history (
        column_id smallint not null references history_columns,
        id int not null,
        change_time timestamp with time zone not null
            constraint change_time_full_second -- only one change allowed per second
                check (date_trunc('second',change_time)=change_time),
        primary key (column_id,id,change_time),
        value text
    );
    

    And on the tables I used a trigger like this:

    create or replace function save_history() returns trigger as
    $$
        if (tg_op = 'DELETE') then
            insert into historia values (
                find_column_id('id',tg_relname), OLD.id,
                date_trunc('second',current_timestamp),
                OLD.id );
            [for each column_name] {
                if (char_length(OLD.column_name)>0) then
                    insert into history values (
                        find_column_id(column_name,tg_relname), OLD.id,
                        OLD.change_time, OLD.column_name
                    )
            }
        elsif (tg_op = 'UPDATE') then
            [for each column_name] {
                if (OLD.column_name is distinct from NEW.column_name) then
                    insert into history values (
                        find_column_id(column_name,tg_relname), OLD.id,
                        OLD.change_time, OLD.column_name
                    );
                end if;
            }
        end if;
    $$ language plpgsql volatile;
    
    create trigger save_history_table1
        before update or delete on table1
        for each row execute procedure save_history();
    

提交回复
热议问题