Как разработать триггер после сервера в Oracle? - PullRequest
6 голосов
/ 11 февраля 2009

Я пытаюсь записать все ошибки в моей базе данных в таблицу. Так как пользователь sys я написал следующий код:

CREATE TABLE servererror_log (
    error_datetime  TIMESTAMP,
    error_user      VARCHAR2(30),
    db_name         VARCHAR2(9),
    error_stack     VARCHAR2(2000),
    captured_sql    VARCHAR2(1000));
/
CREATE OR REPLACE TRIGGER log_server_errors
AFTER SERVERERROR
ON DATABASE
DECLARE
 captured_sql VARCHAR2(1000);
BEGIN
  SELECT q.sql_text
  INTO captured_sql
  FROM gv$sql q, gv$sql_cursor c, gv$session s
  WHERE s.audsid = audsid
  AND s.prev_sql_addr = q.address
  AND q.address = c.parent_handle;

  INSERT INTO servererror_log
  (error_datetime, error_user, db_name,
   error_stack, captured_sql)
  VALUES
  (systimestamp, sys.login_user, sys.database_name,
  dbms_utility.format_error_stack, captured_sql);
END log_server_errors;

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

Есть ли способ проверить, срабатывает ли вообще курок? Кроме того, я попытался создать тестовую таблицу для вставки туда, но она тоже не работает, даже если определить триггер как автономную транзакцию и зафиксировать внутри триггера.

Спасибо, Joaquin

Ответы [ 4 ]

3 голосов
/ 11 февраля 2009

Не запрашивать v $ sql; получить утверждение, используя ora_sql_txt.

CREATE OR REPLACE TRIGGER log_server_errors
AFTER SERVERERROR
ON DATABASE
DECLARE
sql_text ora_name_list_t;
stmt clob;
n number;
BEGIN
  n := ora_sql_txt(sql_text);
  if n > 1000 then n:= 1000; end if ;
  FOR i IN 1..n LOOP
     stmt := stmt || sql_text(i);
   END LOOP;

   INSERT INTO servererror_log
   (error_datetime, error_user, db_name,
    error_stack, captured_sql)
   VALUES
   (systimestamp, sys.login_user, sys.database_name,
   dbms_utility.format_error_stack, stmt);
   commit;
 END log_server_errors;
 /

Тогда:

SQL> select * from c;

Это производит:

select * from c
              *
ERROR at line 1:
ORA-00942: table or view does not exist

К этому теперь можно обратиться:

select * from servererror_log;

Для производства:

ERROR_DATETIME
---------------------------------------------------------------------------
ERROR_USER                     DB_NAME
------------------------------ ---------
ERROR_STACK
--------------------------------------------------------------------------------
CAPTURED_SQL
--------------------------------------------------------------------------------
11-FEB-09 02.55.35.591259 PM
SYS                            TS.WORLD
ORA-00942: table or view does not exist
select * from c
1 голос
/ 17 февраля 2009

Чтобы увидеть, срабатывает ли триггер, добавьте к нему одну или несколько строк следующим образом:

DBMS_OUTPUT.PUT_LINE( 'Got this far' );

В SQLPlus, SET SERVEROUTPUT ON, затем выполните команду для генерации ошибки. Вы должны получить вывод, как это:

dev> select * from aldfjh;
select * from aldfjh
              *
ERROR at line 1:
ORA-00942: table or view does not exist


ORA-00942: table or view does not exist

Got this far
0 голосов
/ 21 октября 2017

Сохранить как ORA-00942.sql:

-- Drop trigger and ignore errors (e.g., not exists).
DECLARE
    existential_crisis EXCEPTION;
    PRAGMA EXCEPTION_INIT( existential_crisis, -4080 );
BEGIN
    EXECUTE IMMEDIATE 'DROP TRIGGER TRG_CATCH_ERRORS /*+ IF EXISTS */';
    EXCEPTION WHEN existential_crisis THEN
    DBMS_OUTPUT.PUT_LINE('Ignoring non-existence.');
END;
/

-- Drop table and ignore errors (e.g., not exists).
DECLARE
    existential_crisis EXCEPTION;
    PRAGMA EXCEPTION_INIT( existential_crisis, -942 );
BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE TBL_ERROR_LOG /*+ IF EXISTS */';
    EXCEPTION WHEN existential_crisis THEN
    DBMS_OUTPUT.PUT_LINE('Ignoring non-existence.');
END;
/

-- Create the table (will not exist due to drop statement).
CREATE TABLE TBL_ERROR_LOG (
    occurred      timestamp,
    account       varchar2(32),
    database_name varchar2(32),
    stack         clob,
    query         clob
);

-- Create the trigger to log the errors.
CREATE TRIGGER TRG_CATCH_ERRORS AFTER servererror ON database
DECLARE
    sql_text   ora_name_list_t;
    n          number;
    query_     clob;
BEGIN
    n := ora_sql_txt( sql_text );

    IF n > 1000 THEN n := 1000; END IF;

    FOR i IN 1 .. n LOOP
        query_ := query_ || sql_text( i );
    END LOOP;

    INSERT INTO TBL_ERROR_LOG
        (occurred, account, database_name, stack, query)
    VALUES
        (systimestamp, sys.login_user, sys.database_name,
     dbms_utility.format_error_stack, query_);
END;
/

Запуск с использованием sqlplus:

SQL> @ORA-00942.sql
PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

Table created.

Trigger created.

Проверьте это:

select * from blargh;
select * from TBL_ERROR_LOG;

Выход:

  2017-10-20 15:15:25.061   SCHEMA  XE  "ORA-00942: table or view does not exist"   select * from blargh
0 голосов
/ 17 февраля 2009

Проверьте состояние вашего триггера и / или наличие других триггеров с помощью:

select trigger_name, status
from all_triggers
where triggering_event like 'ERROR%' 

Это должно привести к:

TRIGGER_NAME        STATUS
------------        -------
LOG_SERVER_ERRORS   ENABLED

Если триггер не включен или другой триггер не работает, он, вероятно, не будет работать.

...