Firebird снова про триггеры. After update, after insert. Что с ними вечно не так?




Найти внятные примеры в интернете мне не удалось. Пришлось как всегда самому все выяснять и разбираться.
After update, after insert ставят перед собой задачу выполнения некоторого кода после update или insert записи в таблице.
Мне нужно было сделать три вещи:
1. Записать в таблицу дату и время создания записи.
2. В таблицу с историей изменений записывать как изменилось поле после update.
3. Записать в таблицу дату и время последнего изменения записи.

Допустим есть таблица CLIENTS такого вида:

ID | NAME | PHONE | CREATE_DATE | MOD_DATE

Решение вопроса №1
Нужно создать триггер, который при добавлении записи, обновлял поле CREATE_DATE. Тут сложностей нет.
CREATE OR ALTER TRIGGER CLIENTS_AI FOR CLIENTS
ACTIVE AFTER INSERT POSITION 0
AS
begin
  update clients set clients.create_date='NOW' where (clients.id = new.id);
end

Так всё работает. При любом добавлении записи, поле CREATE_DATE меняется на актуальную дату.
Решение вопроса №2
Но если мы попробуем так же поступить с after update, то ничего не получится. Тут нужен другой подход:
CREATE OR ALTER TRIGGER CLIENTS_AU FOR CLIENTS
ACTIVE AFTER UPDATE POSITION 1
AS
begin
  if (old.NAME is distinct from new.NAME ) then
     update CLIENTS set mod_date='NOW' where id=old.id;
  if (old.PHONE is distinct from new.PHONE ) then
     update CLIENTS set mod_date='NOW' where id=old.id;
end

Тут уже не так все универсально. Приходится перечислять поля по одному, что не круто, но и мы не из робких. Опять же сравнение происходит по ID и если оно поменяется, запись не создастся.
Ну и самый торт.
Решение вопроса №3
Чтобы реализовать запись изменений, создаем таблицу H_CLIENTS для записи изменений.
ID | FIELD | OLD_VALUE | NEW_VALUE | DATE_TIME |DESCRIPTION

По названию полей можно понять их назначение. Теперь нужно создать триггер, который будет записывать в таблицу H_CLIENTS изменения, сделанные в таблице CLIENTS
CREATE OR ALTER TRIGGER CLIENTS_AUL FOR CLIENTS
ACTIVE AFTER UPDATE POSITION 0
AS
begin
if (old.NAME is distinct from new.NAME ) then
     insert into h_clients (h_clients.id, h_clients.field, h_clients.old_value, h_clients.new_value, h_clients.date_time ,h_clients.description)
            values (old.id, 'NAME', old.NAME, new.NAME,'NOW','Фамилия');
if (old.two_ is distinct from new.two_) then
     insert into h_clients (h_clients.id, h_clients.field, h_clients.old_value, h_clients.new_value, h_clients.date_time ,h_clients.description)
            values (old.id, 'PHONE ', old.PHONE , new.PHONE ,'NOW','Телефон');
end

Получается, что условие опять задано для каждого поля. При update одного из них, в таблицу h_client запишутся ID клиента, старое значение поля, новое значение поля, дата-время и описание поля.
Конструкция is distinct from в условии это находка для меня. Так как Google на попытки поиска примеров триггеров с условиями отвечает ерундой.
Вот как бы и всё.