You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PL/SQL触发器编译报错:ORA-00920无效关系运算符

Oracle 19c触发器编译报错排查

环境:Oracle 19c(兼容12c)

以下是我的触发器代码:

CREATE OR REPLACE TRIGGER ClientTime
AFTER INSERT OR UPDATE OR DELETE ON ClientTime
FOR EACH ROW
DECLARE
  v_pk_json CLOB;
  v_changed CLOB;
  v_old_part VARCHAR2(32767);
  v_new_part VARCHAR2(32767);
  v_first_old BOOLEAN;
  v_first_new BOOLEAN;
BEGIN
  -- build pk json
  v_pk_json := '{' || 
    CASE 
      WHEN INSERTING OR UPDATING THEN '"id":' || NVL(TO_CHAR(:NEW.ID),'null') 
      ELSE '"id":' || NVL(TO_CHAR(:OLD.ID),'null') 
    END || 
  '}'; 

  -- build changed columns json
  IF INSERTING THEN  
    v_changed := '{' || 
      '"id":' || NVL(TO_CHAR(:NEW.ID), 'null') || ',' || 
      '"client":' || NVL(TO_CHAR(:NEW.CLIENT), 'null') || ',' || 
      '"timestamp":"' || NVL(TO_CHAR(:NEW.DATETIME, 'YYYY-MM-DD HH24:MI:SS'), 'null') || '"' ||
    '}';

  ELSIF DELETING THEN
    v_changed := '{' || 
      '"id":' || NVL(TO_CHAR(:OLD.ID), 'null') || ',' || 
      '"client":' || NVL(TO_CHAR(:OLD.CLIENT), 'null') || ',' || 
      '"timestamp":"' || NVL(TO_CHAR(:OLD.DATETIME, 'YYYY-MM-DD HH24:MI:SS'), 'null') || '"' ||
    '}'; 

  ELSE -- UPDATE: only changed columns
    v_old_part := '{';
    v_new_part := '{';
    v_first_old := TRUE;
    v_first_new := TRUE;

    IF NVL(:OLD.CLIENT, -999999) <> NVL(:NEW.CLIENT, -999999) THEN
      v_old_part := v_old_part || '&quot;client&quot;:' || NVL(TO_CHAR(:OLD.CLIENT),'null');
      v_new_part := v_new_part || '&quot;client&quot;:' || NVL(TO_CHAR(:NEW.CLIENT),'null');
      v_first_old := FALSE;
      v_first_new := FALSE;
    END IF;

    IF NVL(:OLD.DATETIME, TO_DATE('1900-01-01','YYYY-MM-DD')) <> NVL(:NEW.DATETIME, TO_DATE('1900-01-01','YYYY-MM-DD')) THEN
      IF NOT v_first_old THEN
        v_old_part := v_old_part || ',';
        v_new_part := v_new_part || ',';
      END IF;
      v_old_part := v_old_part || '&quot;timestamp&quot;:&quot;' || NVL(TO_CHAR(:OLD.DATETIME,'YYYY-MM-DD HH24:MI:SS'),'null') || '&quot;';
      v_new_part := v_new_part || '&quot;timestamp&quot;:&quot;' || NVL(TO_CHAR(:NEW.DATETIME,'YYYY-MM-DD HH24:MI:SS'),'null') || '&quot;';
    END IF;

    v_old_part := v_old_part || '}';
    v_new_part := v_new_part || '}';
    v_changed := '{&quot;old&quot;:' || v_old_part || ',&quot;new&quot;:' || v_new_part || '}';
  END IF;
  -- insert into audit_log
  INSERT INTO audit_log(change_txid, scn, change_ts, db_user, session_id, client_host, module_name,
                        schema_name, table_name, op_type, pk_json, changed_columns)
  VALUES (DBMS_TRANSACTION.LOCAL_TRANSACTION_ID, ORA_ROWSCN, SYSTIMESTAMP,
          SYS_CONTEXT('USERENV','SESSION_USER'), SYS_CONTEXT('USERENV','SESSIONID'),
          SYS_CONTEXT('USERENV','HOST'), SYS_CONTEXT('USERENV','MODULE'),
          'DBNAME','CLIENTTIME',
          CASE WHEN INSERTING THEN 'I' WHEN UPDATING THEN 'U' ELSE 'D' END,
          v_pk_json, v_changed);

END;

注:为安全起见修改了列名,实际中Datetime并非Oracle关键字。

编译报错:

PL/SQL: SQL Statement ignored
PL/SQL: ORA-00920: invalid relational operator

我已尝试以下修改但均无效:

  • 将SYS_CONTEXT('USERENV', 'SESSION_USER')改为USER
  • 将SYS_CONTEXT('USERENV', 'SESSIONID')改为SESSIONID
  • 将SYS_CONTEXT('USERENV', 'HOST')改为HOST
  • 提前INSERT语句中的CASE逻辑

我认为代码存在结构性问题但无法定位。

更新:将INSERT语句修改为以下内容后,触发器已编译成功:

INSERT INTO audit_log(change_txid, scn, change_ts, db_user, session_id, client_host, module_name,
                      schema_name, table_name, op_type, pk_json, changed_columns)
VALUES (NULL, NULL, SYSDATE, USER, NULL, NULL,NULL, 'DBNAME','CLIENTTIME', 'I', v_pk_json, v_changed);

内容的提问来源于stack exchange,提问作者davejal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 05:12:40