четверг, 22 ноября 2012 г.

ORACLE: логирование всех DDL операций.

Вот такой небольшой триггер позволит сохранить все операции DDL, происходящие во всех схемах БД. DDL (Data Definition Language) - описание структур объектов базы.
Триггер выполняется после DDL операции и сохраняет: тип объекта (ora_dict_obj_type), схему (ora_dict_obj_owner), имя объекта (ora_dict_obj_name), имя пользователя , дата операции, тип DDL операции (ora_sysevent), имя компьютера и CLOB с текстом DDL операции (ora_sql_txt).
create or replace TRIGGER bi_sa_psk.trg_ddl_trig_hist
 AFTER DDL
 ON DATABASE
declare
  PRAGMA AUTONOMOUS_TRANSACTION;

  v_ddl CLOB := EMPTY_CLOB;
  li ora_name_list_t;
  l_n number;
BEGIN
  /* sys создает системные временные таблицы для sql запросов */
  IF ora_dict_obj_owner = 'SYS' THEN
    return;
  END IF;

  /* Получим текст DDL */
  l_n := ora_sql_txt(li);
  for i in 1 .. l_n loop
    v_ddl := v_ddl || TO_CLOB(TO_CHAR(li(i)));
  end loop;

  /* запишем историю */
  INSERT INTO bi_sa_psk.ddl_hist(object_type, owner, object_name, USER_NAME, DDL_DATE, DDL_TYPE, COMP_NAME, DDL_TXT, stack)
  VALUES(UPPER(ora_dict_obj_type), UPPER(ora_dict_obj_owner), UPPER(ora_dict_obj_name), ora_login_user, SYSDATE, ora_sysevent, SYS_CONTEXT ('USERENV', 'OS_USER'), v_ddl, dbms_utility.format_call_stack);
  commit;

  /* любые ошибки игнорируем, что бы не завалить БД целиком */
  EXCEPTION WHEN OTHERS THEN NULL;
END trg_ddl_trig_hist;
/
Такая штука будет очень полезна, чтобы вернуть утерянные изменения или отыскать виновного в баге :) .