1

我已经尽力自己做到这一点,但我无处可去。这是我的触发器定义:

CREATE OR REPLACE TRIGGER KK_BUDGET_TYPE_TR AFTER
  INSERT OR
  UPDATE OR
  DELETE ON PS_KK_BUDGET_TYPE FOR EACH ROW DECLARE V_AUDIT_OPRID VARCHAR2(64);

  V_JOB_NUMBER NUMBER;
  BEGIN
    DBMS_APPLICATION_INFO.READ_CLIENT_INFO(V_AUDIT_OPRID);
    IF INSERTING THEN
      INSERT
      INTO PS_KK_BD_TYPE_AUD VALUES
        (
          GET_PS_OPRID(V_AUDIT_OPRID),
          SYSDATE,
          'A',
          :NEW.SETID1,
          :NEW.LEDGER_GROUP,
          :NEW.EFFDT,
          :NEW.EFF_STATUS,
          :NEW.CNTRL_OPTN,
          :NEW.BUDGET_STATUS,
          :NEW.DESCR,
          :NEW.BUDG_TYPE,
          :NEW.ASSOC_EXP_BD,
          :NEW.PARENT_BUDGET,
          :NEW.CHILD_EXCEED,
          :NEW.CONTROL_CHARTFIELD,
          :NEW.ALL_VALUES,
          :NEW.FILTER_CHARTFIELD,
          :NEW.TREE_NAME,
          :NEW.TREE_LEVEL,
          :NEW.ENABLE_FS,
          :NEW.KK_REV_TRACK_LG,
          :NEW.TOLERANCE,
          :NEW.BALANCED_LINES,
          :NEW.KK_ENABLE_STAT,
          :NEW.SUBTYPE,
          :NEW.EXPIRE_CHARTFIELD
        );
    ELSE
      IF DELETING THEN
        INSERT
        INTO PS_KK_BD_TYPE_AUD VALUES
          (
            GET_PS_OPRID(V_AUDIT_OPRID),
            SYSDATE,
            'D',
            :OLD.SETID1,
            :OLD.LEDGER_GROUP,
            :OLD.EFFDT,
            :OLD.EFF_STATUS,
            :OLD.CNTRL_OPTN,
            :OLD.BUDGET_STATUS,
            :OLD.DESCR,
            :OLD.BUDG_TYPE,
            :OLD.ASSOC_EXP_BD,
            :OLD.PARENT_BUDGET,
            :OLD.CHILD_EXCEED,
            :OLD.CONTROL_CHARTFIELD,
            :OLD.ALL_VALUES,
            :OLD.FILTER_CHARTFIELD,
            :OLD.TREE_NAME,
            :OLD.TREE_LEVEL,
            :OLD.ENABLE_FS,
            :OLD.KK_REV_TRACK_LG,
            :OLD.TOLERANCE,
            :OLD.BALANCED_LINES,
            :OLD.KK_ENABLE_STAT,
            :OLD.SUBTYPE,
            :OLD.EXPIRE_CHARTFIELD
          );
      ELSE
        INSERT
        INTO PS_KK_BD_TYPE_AUD VALUES
          (
            GET_PS_OPRID(V_AUDIT_OPRID),
            SYSDATE,
            'K',
            :OLD.SETID1,
            :OLD.LEDGER_GROUP,
            :OLD.EFFDT,
            :OLD.EFF_STATUS,
            :OLD.CNTRL_OPTN,
            :OLD.BUDGET_STATUS,
            :OLD.DESCR,
            :OLD.BUDG_TYPE,
            :OLD.ASSOC_EXP_BD,
            :OLD.PARENT_BUDGET,
            :OLD.CHILD_EXCEED,
            :OLD.CONTROL_CHARTFIELD,
            :OLD.ALL_VALUES,
            :OLD.FILTER_CHARTFIELD,
            :OLD.TREE_NAME,
            :OLD.TREE_LEVEL,
            :OLD.ENABLE_FS,
            :OLD.KK_REV_TRACK_LG,
            :OLD.TOLERANCE,
            :OLD.BALANCED_LINES,
            :OLD.KK_ENABLE_STAT,
            :OLD.SUBTYPE,
            :OLD.EXPIRE_CHARTFIELD
          );
        INSERT
        INTO PS_KK_BD_TYPE_AUD VALUES
          (
            GET_PS_OPRID(V_AUDIT_OPRID),
            SYSDATE,
            'N',
            :NEW.SETID1,
            :NEW.LEDGER_GROUP,
            :NEW.EFFDT,
            :NEW.EFF_STATUS,
            :NEW.CNTRL_OPTN,
            :NEW.BUDGET_STATUS,
            :NEW.DESCR,
            :NEW.BUDG_TYPE,
            :NEW.ASSOC_EXP_BD,
            :NEW.PARENT_BUDGET,
            :NEW.CHILD_EXCEED,
            :NEW.CONTROL_CHARTFIELD,
            :NEW.ALL_VALUES,
            :NEW.FILTER_CHARTFIELD,
            :NEW.TREE_NAME,
            :NEW.TREE_LEVEL,
            :NEW.ENABLE_FS,
            :NEW.KK_REV_TRACK_LG,
            :NEW.TOLERANCE,
            :NEW.BALANCED_LINES,
            :NEW.KK_ENABLE_STAT,
            :NEW.SUBTYPE,
            :NEW.EXPIRE_CHARTFIELD
          );
      END IF;
    END IF;
    DBMS_JOB.submit
    (
      job => V_JOB_NUMBER, what => 'logger "KK_BD_TYPE_AUD_CHG"', next_date => SYSDATE
    )
    ;
  END KK_BUDGET_TYPE_TR;

除了“由于提交问题,这是一个糟糕的想法”之外,这正是我们想要发生的事情,即使发生回滚等等。某处的某些代码正在更新某些用户不应该能够更新的表。我们完全无法确定用户在做什么,因此我们可以复制问题,因此我们当前的目标是立即获得特定表上数据已更改的通知,然后让我们立即联系用户以找出他们当时在做什么。系统管理员想在 syslog 上放置一个过滤器,所以他希望我使用以下行运行命令行

logger "KK_BD_TYPE_AUD_CHG"

结果是

ORA-06550: line 1, column 100:
PLS-00103: Encountered the symbol "KK_BD_TYPE_AUD_CHG" when expecting one of the following:
:= . ( @ % ;
The symbol "; was inserted before "KK_BD_TYPE_AUD_CHG" to continue.

所以在这一点上我很茫然,我已经脱离了我的元素。任何帮助或替代选项将不胜感激。

4

1 回答 1

0

由于logger是操作系统可执行文件,因此不能直接从 PL/SQL 调用它,因此不能直接从dbms_job.

您可以创建一个 Java 存储过程,该过程将使用 Java 操作系统 API 调用操作系统,将该 Java 存储过程的适当权限授予 Oracle 所有者,在 Java 存储过程上创建一个 PL/SQL 包装器,然后调用那个 PL/SQL 包装器来自dbms_job. 这将是相当多的移动部件,但网上有多个这样做的例子。这个askTom关于调用主机操作系统的Java存储过程的问题可能是最好的例子。但是请注意,如果您允许调用者传递任意调用,攻击者可以使用它来运行他们想要的任何操作系统命令,因为任何操作系统用户在主机操作系统上运行 Oracle 数据库。这将允许能够调用您的过程的攻击者基本上对您的数据库执行他们想要的任何操作,因此这是一个严重的安全问题。

dbms_scheduler使用而不是调用主机操作系统会更少的移动部件dbms_job- 这是一个从 dbms_scheduler 创建和调用可执行程序的示例。但是您不能dbms_scheduler在触发器中创建日志,因为这样做需要隐式提交。您可以通过将触发器声明为自主事务来解决此问题。通常,这不是一个选项,但因为听起来您并不担心在事务回滚时收到警报,所以这对您来说可能是一个合理的选择。

于 2013-10-30T20:38:08.270 回答