powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Логирование изменений
13 сообщений из 13, страница 1 из 1
Логирование изменений
    #39861031
romero111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Опишу задачу: необходимо логировать данные в БД, пока только удаление. Знаю, что в IBExpert есть своя штука для этого. Но хочется под себя. Чтобы написанный один единственный триггер / процедуру можно было размножить на все таблицы с минимальными изменениями самого триггера / процедуры. Созданы две таблицы LOG_TABLES, LOG_FIELDS.
Алгоритм решения: из системных таблиц нахожу все поля конкретной таблицы, для которой хочу после удаления из нее записи сделать лог в таблицах логирования. Значение old для каждого поля пишем в таблицу логирования. Все.
Проблема: хочу к контекстной переменной Old добавить названия полей и именно это значение писать в лог-таблицу. Т.е. неким образом превратить ее опять в контекстную после конкатенации и выполнить запись. Возможно это?

:context_old_value = 'old.'||lower(:field_name);
:deleted_value = :context_old_value;
s = 'insert into LOG_FIELDS (LOG_TABLE_ID,FIELD_NAME, FIELD_TYPE, OLD_VALUE) values (?,?,?,?)';
execute statement (:s) (:sequence_id,:field_name,:type_data,:deleted_value)

Записывает он здесь, конечно, как текст.
...
Рейтинг: 0 / 0
Логирование изменений
    #39861046
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
romero111,

создай себе процедуру которая автоматически будет генерировать текст логирующего триггера для произвольной таблицы.
Потом выполни эту ХП для всех нужных таблиц из результатов собери скрипт. Это не сложно.
...
Рейтинг: 0 / 0
Логирование изменений
    #39861051
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. нужно учитывать NULL-ы
2. вещественные числа
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Логирование изменений
    #39861062
romero111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я и собираюсь составить некий текст триггера. Но пробела в том, что я соберу все названия полей таблицы: пусть 'field1', 'field2', 'field3'. Присобачу к OLD это имя - и это уже будет текст, а не контекстная переменная.
В переменной ins_field_value = названия поля таблицы = 'field1'.
insert into log_table (field_name,flield_value) values ('field1','old.'||ins_field_value )
Он вставить запись в flield_value как текст = 'old.field1'. Мне же надо, что он взял как контекстную переменную этот параметр и вставил туда значение поля field1.
...
Рейтинг: 0 / 0
Логирование изменений
    #39861063
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
romero111я и собираюсь составить некий текст триггера.

Обломись. Не может быть "универсального протоколирующего триггера".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Логирование изменений
    #39861077
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
romero111,

тебе говорят собирай текст триггера целиком как строку и скармливай её выполнителю скрипта
...
Рейтинг: 0 / 0
Логирование изменений
    #39861178
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakovromero111я и собираюсь составить некий текст триггера.

Обломись. Не может быть "универсального протоколирующего триггера".Ну почему же.
Такая задача, и многие другие, уже решены здесь:
http://button.dekel.ru/
...
Рейтинг: 0 / 0
Логирование изменений
    #39861335
romero111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Симонов Денис, процка создана (где входящие параметры Таблица и Операция). Создается длиннющая строка текста триггера. Но проблема то этим не решилась: я ее (строку) вставляю в выполнитель скриптов, но последняя моя операция в этом скрипте, как и описано в самом первом сообщении, никак не преобразилась. Т.е. она осталась текстовым полем, а мне ее надо скормить как old.field_name, а не как 'old.field_name'.
Задача: я беру все поля таблицы и хочу записать их значения при удалении из таблицы в таблицу лога. Делать хочу это в триггере на before_delete. Где есть контекстная переменная OLD. Хочу к ней в цикле (или как хотите называйте) присобачивать по очереди названия полей и получать значение, которые записывать в лог. С присобавчиванием (конкатенацией) проблем нет, есть проблема, что эта переменная уже не является контекстной и не выполняет свои "функции", а просто превратилась в текст.
...
Рейтинг: 0 / 0
Логирование изменений
    #39861358
KreatorXXI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
romero111,

"execute statement" не выполняет скрипт? Или что?
...
Рейтинг: 0 / 0
Логирование изменений
    #39861363
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
romero111,

ещё раз объясняю. Так сделать нельзя. Поля после OLD надо указывать в явном виде. Т.е. создать универсальный триггер не получится, но можно сделать процедуру которая облегчит написание таких триггеров.
Вот кусок моего пакета для записи логов. Тебе он не подойдёт, но ты можешь уловить мысль

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
  PROCEDURE CREATE_UPDATE_TRIGGER(ATable VARCHAR(31)) RETURNS (SQL_TEXT BLOB SUB_TYPE TEXT)
  AS
    DECLARE EOL CHAR(2);
    DECLARE PK_FIELDNAME VARCHAR(31);
  BEGIN
    ATable = TRIM(ATable);
    SELECT
      TRIM(IND.RDB$FIELD_NAME) AS FIELD_NAME
    FROM RDB$RELATION_CONSTRAINTS RC
      JOIN RDB$INDEX_SEGMENTS IND ON IND.RDB$INDEX_NAME = RC.RDB$INDEX_NAME
    WHERE RC.RDB$RELATION_NAME = :ATable AND RC.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
    INTO PK_FIELDNAME;

    EOL = ASCII_CHAR(13) || ASCII_CHAR(10);
    SQL_TEXT = 'CREATE OR ALTER TRIGGER TR_' || ATable || '_REPL_AU FOR ' || ATable || EOL;
    SQL_TEXT = SQL_TEXT || 'ACTIVE AFTER UPDATE POSITION 0' || EOL;
    SQL_TEXT = SQL_TEXT || 'AS' || EOL;
    SQL_TEXT = SQL_TEXT || '  DECLARE LOG_ID INT;' || EOL;
    SQL_TEXT = SQL_TEXT || 'BEGIN' || EOL;

    SQL_TEXT = SQL_TEXT || '  EXECUTE PROCEDURE REPL_WRITE_LOG.BEGIN_OPERATION(' || '''' || ATable || ''', ''U'', ''' || PK_FIELDNAME || ''', OLD.' || PK_FIELDNAME || ') RETURNING_VALUES LOG_ID;' || EOL;
    FOR
      SELECT
           F.FIELD_SOURCE AS FIELD_NAME,
           F.FIELD_TYPE,
           F.FIELD_SCALE,
           F.FIELD_POS
      FROM
          TABLE_MAP T
          JOIN FIELD_MAP F ON F.CODE_TABLE_MAP = T.CODE_TABLE_MAP
      WHERE T.CODE_SENDER = 1 AND T.TABLE_SOURCE = :ATable
      ORDER BY F.FIELD_POS
      AS CURSOR C
    DO
    BEGIN
      SQL_TEXT = SQL_TEXT || '  IF (NEW.' || C.FIELD_NAME || ' IS DISTINCT FROM OLD.' || C.FIELD_NAME || ') THEN' || EOL;
      SQL_TEXT = SQL_TEXT || '    EXECUTE PROCEDURE REPL_WRITE_LOG.WRITE_' || C.FIELD_TYPE ||'_VALUE(LOG_ID, ''' || C.FIELD_NAME || ''', NEW.' || C.FIELD_NAME || ');' || EOL;
    END
    SQL_TEXT = SQL_TEXT || 'END' || EOL;
    SUSPEND;
  END
...
Рейтинг: 0 / 0
Логирование изменений
    #39861375
romero111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KreatorXXI, выполняется, но не хочет понимать old.tag_id, например. Сейчас :field_name = tag_id.

:field_value = 'old.' || lower(:field_name);

execute statement 'insert into LOG_FIELDS (LOG_TABLE_ID,FIELD_NAME, FIELD_TYPE, INT_VALUE) values (' || :sequence_id || ',''' || :field_name || ''',''' || :type_data || ''',' || :field_value || ')'
on external :setting_value
as user :user_login password :user_pass;

Пишет, что не знает такое поле....
...
Рейтинг: 0 / 0
Логирование изменений
    #39861377
romero111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Симонов Денис,

красиво. Спасибо, что поделились творчеством. Полезная идея.
...
Рейтинг: 0 / 0
Логирование изменений
    #39861476
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
romero111,

оператор, выполняемый execute statement не имеет доступа к "внешнему" контексту. Допустим, когда оно вызывается из триггера, оператор ES ни про какой триггер понятия не имеет. Он выполняется точно так же, как любой клиентский запрос.
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Логирование изменений
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]