简体   繁体   中英

Missing privilege - Oracle System event trigger problem 12c

I have a system event trigger. It worked fine until I tried to move the code to a different database. I made a mistake: forgot to export the original user, so I created a total new one.

So after I release my code I get the error:

Compilation errors for TRIGGER ORACLE_VERSION_CONTROLLER.TRG_CATCH_AFTER_DDL

Error: PLS-00201: identifier 'ORA_SQL_TXT' must be declared Line: 24 Text: n := ora_sql_txt(sql_text);

Error: PL/SQL: Statement ignored Line: 24 Text: n := ora_sql_txt(sql_text);

Anyone has an idea?

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;

I am able to create this trigger from the non-sys user.

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

Output:

在此处输入图片说明

Hope, It will be useful to you.

Cheers!!

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM