权限缺失-Oracle系统事件触发问题12c

Missing privilege - Oracle System event trigger problem 12c

我有一个系统事件触发器。在我尝试将代码移动到不同的数据库之前,它工作正常。 我弄错了:忘记导出原来的用户,所以我创建了一个全新的。

因此在我发布代码后出现错误:

TRIGGER 的编译错误 ORACLE_VERSION_CONTROLLER.TRG_CATCH_AFTER_DDL

错误:PLS-00201:必须声明标识符 'ORA_SQL_TXT' 线路:24 文本:n := ora_sql_txt(sql_text);

错误:PL/SQL:语句被忽略 线路:24 文本:n := ora_sql_txt(sql_text);

有人有想法吗?

CREATE OR REPLACE TRIGGER trg_catch_after_ddl
  AFTER DDL ON DATABASE
DECLARE
  sql_text ora_name_list_t;
  n        pls_integer;
  v_sql    CLOB;
  v_id     NUMBER;

BEGIN

  dbms_output.put_line(ora_sysevent);

  IF ora_sysevent IN ('DROP', 'ALTER', 'ANALYZE') THEN
    /*alter table must be handle*/
    NULL; -- this is not finished
  ELSE

    IF ora_dict_obj_type = 'TABLE' THEN
      v_sql := dbms_metadata.get_ddl(ora_dict_obj_type,
                                     ora_dict_obj_name,
                                     ora_login_user);
    ELSE

      n := ora_sql_txt(sql_text);


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

    END IF;
    INSERT INTO audit_log
      (user_name, dll_type, object_name, object_type, object_script)
    VALUES
      (ora_login_user,
       ora_sysevent,
       ora_dict_obj_name,
       ora_dict_obj_type,
       v_sql)
    RETURNING log_id INTO v_id;

    pcd_source_writer(id => v_id);

  END IF;

END trg_catch_after_ddl;

解决方法是该函数需要在sys用户下,并赋予执行权限。

我可以从 non-sys 用户创建这个触发器。

-- Execute from sys user

CREATE USER T IDENTIFIED BY <Password>
default tablespace <Default_tablespace>;

ALTER USER T QUOTA UNLIMITED ON <Default_tablespace>;

GRANT CONNECT, RESOURCE TO T;

GRANT ADMINISTER DATABASE TRIGGER TO T;

--

-- Execute from T user


CREATE TABLE AUDIT_LOG (
    LOG_ID          NUMBER
        GENERATED ALWAYS AS IDENTITY,
    USER_NAME       VARCHAR2(4000),
    DLL_TYPE        VARCHAR2(4000),
    OBJECT_NAME     VARCHAR2(4000),
    OBJECT_TYPE     VARCHAR2(4000),
    OBJECT_SCRIPT   CLOB
);


CREATE OR REPLACE TRIGGER TRG_CATCH_AFTER_DDL AFTER DDL ON DATABASE DECLARE
    SQL_TEXT   ORA_NAME_LIST_T;
    N          PLS_INTEGER;
    V_SQL      CLOB;
    V_ID       NUMBER;
BEGIN
    DBMS_OUTPUT.PUT_LINE(ORA_SYSEVENT);
    IF ORA_SYSEVENT IN (
        'DROP',
        'ALTER',
        'ANALYZE'
    ) THEN
    /*alter table must be handle*/
        NULL; -- this is not finished
    ELSE
        IF ORA_DICT_OBJ_TYPE = 'TABLE' THEN
            V_SQL := DBMS_METADATA.GET_DDL(ORA_DICT_OBJ_TYPE, ORA_DICT_OBJ_NAME, ORA_LOGIN_USER);
        ELSE
            N := ORA_SQL_TXT(SQL_TEXT);
            FOR I IN 1..N LOOP
                V_SQL := V_SQL || SQL_TEXT(I);
            END LOOP;

        END IF;
    INSERT INTO audit_log
      (user_name, dll_type, object_name, object_type, object_script)
    VALUES
      (ora_login_user,
       ora_sysevent,
       ora_dict_obj_name,
       ora_dict_obj_type,
       v_sql)
    RETURNING log_id INTO v_id;
--
--    pcd_source_writer(id => v_id);
    END IF;

END TRG_CATCH_AFTER_DDL;
/

--

-- Testing:

DROP SEQUENCE TEMP_SEQ;
CREATE SEQUENCE TEMP_SEQ START WITH 1 INCREMENT BY 1 MAXVALUE 100;
ALTER SEQUENCE TEMP_SEQ INCREMENT BY 2;

--

-- Result:

SELECT * FROM audit_log;

输出:

希望对你有用。

干杯!!