缺少特权-Oracle系统事件触发器问题12c

时间:2019-06-24 06:33:24

标签: oracle plsql database-trigger

我有一个系统事件触发器。在我尝试将代码移至其他数据库之前,它一直运行良好。 我犯了一个错误:忘记导出原始用户,所以我创建了一个新用户。

因此,在发布代码后,我得到了错误:

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;

2 个答案:

答案 0 :(得分:2)

我能够从非系统用户创建此触发器。

-- 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;

输出:

enter image description here

希望,对您有用。

干杯!

答案 1 :(得分:1)

解决方案是该功能必须在sys用户下并具有执行特权。