Создать триггер таблицы истории DB2 - PullRequest
4 голосов
/ 11 ноября 2008

Я хочу создать таблицу истории, чтобы отслеживать изменения полей в нескольких таблицах в DB2.

Я знаю, что история обычно делается с копированием структуры всей таблицы и присвоением ей суффиксного имени (например, user -> user_history). Затем вы можете использовать довольно простой триггер, чтобы скопировать старую запись в таблицу истории при ОБНОВЛЕНИИ.

Однако для моего приложения это заняло бы слишком много места. Не кажется хорошей идеей (по крайней мере, мне) копировать всю запись в другую таблицу каждый раз, когда поле изменяется. Поэтому я подумал, что у меня может быть общая таблица истории, которая будет отслеживать изменения отдельных полей:

CREATE TABLE history
(
    history_id LONG GENERATED ALWAYS AS IDENTITY,
    record_id INTEGER NOT NULL,
    table_name VARCHAR(32) NOT NULL,
    field_name VARCHAR(64) NOT NULL,
    field_value VARCHAR(1024),
    change_time TIMESTAMP,
    PRIMARY KEY (history_id)
);

ОК, поэтому каждая таблица, которую я хочу отслеживать, имеет одно автоматически генерируемое поле идентификатора в качестве первичного ключа, которое будет помещено в поле record_id. И максимальный размер VARCHAR в таблицах составляет 1024. Очевидно, что если поле, отличное от VARCHAR, изменится, его нужно будет преобразовать в VARCHAR перед вставкой записи в таблицу истории.

Теперь, это может быть полностью запаздывающий способ сделать что-то (эй, дайте мне знать, почему, если это так), но я думаю, что это хороший способ отслеживания изменений, которые нужно редко проверять и хранить в течение значительного количества времени.

В любом случае, мне нужна помощь в написании триггера для добавления записей в таблицу истории при обновлении. Например, возьмем гипотетическую таблицу пользователей:

CREATE TABLE user
(
   user_id INTEGER GENERATED ALWAYS AS IDENTITY,
   username VARCHAR(32) NOT NULL,
   first_name VARCHAR(64) NOT NULL,
   last_name VARCHAR(64) NOT NULL,
   email_address VARCHAR(256) NOT NULL
   PRIMARY KEY(user_id)
);

Итак, кто-нибудь может мне помочь с триггером на обновление пользовательской таблицы, чтобы вставить изменения в таблицу истории? Я предполагаю, что какой-то процедурный SQL нужно будет использовать для циклического обхода полей в старой записи, сравнения их с полями в новой записи и, если они не совпадают, то добавления новой записи в таблицу истории.

Было бы предпочтительно использовать один и тот же SQL-код действия триггера для каждой таблицы, независимо от ее полей, если это возможно.

Спасибо!

Ответы [ 4 ]

1 голос
/ 14 ноября 2008
CREATE TABLE HIST.TB_HISTORY ( 
    HIST_ID     BIGINT GENERATED ALWAYS AS IDENTITY (START WITH 0, INCREMENT BY 1, NO CACHE) NOT NULL,
    HIST_COLUMNNAME     VARCHAR(128) NOT NULL,
    HIST_OLDVALUE       VARCHAR(255),
    HIST_NEWVALUE       VARCHAR(255),
    HIST_CHANGEDDATE    TIMESTAMP NOT NULL
    PRIMARY KEY(HIST_SAFTYNO)
)
GO


CREATE TRIGGER COMMON.TG_BANKCODE AFTER
UPDATE OF FRD_BANKCODE ON COMMON.TB_MAINTENANCE
REFERENCING OLD AS oldcol NEW AS newcol FOR EACH ROW MODE DB2SQL
WHEN(COALESCE(newcol.FRD_BANKCODE,'#null#') <> COALESCE(oldcol.FRD_BANKCODE,'#null#'))
BEGIN ATOMIC

    CALL FB_CHECKING.SP_FRAUDHISTORY_ON_DATACHANGED(
                newcol.FRD_FRAUDID,
                'FRD_BANKCODE',
                oldcol.FRD_BANKCODE,
                newcol.FRD_BANKCODE,
                newcol.FRD_UPDATEDBY
    );--

    INSERT INTO FB_CHECKING.TB_FRAUDMAINHISTORY(        
        HIST_COLUMNNAME, 
        HIST_OLDVALUE, 
        HIST_NEWVALUE, 
        HIST_CHANGEDDATE
1 голос
/ 11 ноября 2008

Рассматривали ли вы сделать это в два этапа? Реализуйте простой триггер, который записывает исходную и измененную версию всей строки. Затем напишите отдельную программу, которая запускается один раз в день для извлечения измененных полей, как описано выше.

Это делает триггер проще, безопаснее, быстрее, и у вас есть больше возможностей для реализации этапа постобработки.

1 голос
/ 11 ноября 2008

Мы делаем нечто похожее с нашей базой данных SQL Server, но таблицы аудита предназначены для каждой отдельной проверяемой таблицы (одна центральная таблица будет огромной, поскольку наша база данных имеет много много гигабайт)

Одна вещь, которую вам нужно сделать, это убедиться, что вы также записали, кто внес изменения. Вы также должны записать старое и новое значение вместе (облегчает возврат данных, если вам нужно) и тип изменения (вставить, обновить, удалить). Вы не упоминаете удаления записей из таблицы, но мы находим в них те вещи, для которых мы чаще всего используем таблицу.

Мы используем динамический SQl для генерации кода для создания таблиц аудита (с помощью таблицы, в которой хранится системная информация), и все таблицы аудита имеют точно такую ​​же структуру (что облегчает возврат данных).

Когда вы создаете код для хранения данных в своей таблице истории, также создайте код для восстановления данных в случае необходимости. Это сэкономит массу времени в будущем, когда что-то нужно будет восстановить, и вы находитесь под давлением высшего руководства, чтобы сделать это сейчас.

Теперь я не знаю, планировали ли вы восстановить данные из своей таблицы истории, но как только вы это сделаете, я могу гарантировать, что руководство захочет использовать их таким образом.

1 голос
/ 11 ноября 2008

Я не думаю, что это хорошая идея, поскольку вы генерируете еще больше накладных расходов на значение с большой таблицей, в которой изменяется более одного значения. Но это зависит от вашего приложения.

Кроме того, вы должны рассмотреть практическую ценность такой таблицы истории. Вы должны собрать множество строк, чтобы хотя бы взглянуть на контекст измененного значения, и вам потребуется кодировать другое приложение, которое выполняет только эту сложную логику истории для конечного пользователя. А для администратора БД было бы неудобно восстанавливать значения из истории.

это может звучать немного грубо, но это не цель. У опытного программиста в нашем магазине возникла схожая идея с ведением журналов за столом. Он запустил его и запустил, но он съел дисковое пространство, как будто завтра нет.

Подумайте, чего на самом деле должна достичь ваша таблица истории.

...