Oracle PL/SQL触发器未评估条件是否符合预期

Oracle PL/SQL触发器未评估条件是否符合预期,oracle,plsql,eventtrigger,Oracle,Plsql,Eventtrigger,我很难让这一小块pl/sql工作! 如果有人能找出什么是真正的阻碍? 脚本的目的是审核导致帐户过期或锁定的DDLalter user操作 我试着用dbms\u output.put\u line调试它,但它似乎没有将IF(user\u status\u16和l\u action='LOCK')评估为TRUE。很可能是变量l\u action的问题,因为当我删除它时,当满足cond user\u status\u16时,它会在表中记录一些内容 但是,如果我使用dbms_output.put_行('

我很难让这一小块pl/sql工作! 如果有人能找出什么是真正的阻碍? 脚本的目的是审核导致帐户过期或锁定的DDL
alter user
操作

我试着用
dbms\u output.put\u line
调试它,但它似乎没有将
IF(user\u status\u16和l\u action='LOCK')
评估为TRUE。很可能是变量
l\u action
的问题,因为当我删除它时,当满足cond user\u status\u16时,它会在表中记录一些内容

但是,如果我使用
dbms_output.put_行('action:'| | l_action)打印l_action它向我显示正确的值。见下文

Trigger created.

SQL>
SQL>
SQL> alter user PERFSTAT account lock;
action: LOCK
这是我的扳机:

CREATE OR REPLACE 
TRIGGER trg_lock_track AFTER ALTER ON DATABASE
WHEN (ora_dict_obj_type = 'USER')
DECLARE
  session_id VARCHAR2(50);
  ip_addr    VARCHAR2(50);
  hostname   VARCHAR2(50);
  auth_type  VARCHAR2(50);
  l_session_user  VARCHAR2(50);
  l_module  VARCHAR2(100);
  l_osuser  VARCHAR2(50);
  user_name_ VARCHAR2(50);
  user_status_ NUMBER;  
  user_datelock_ DATE;  
  user_dateexp_ DATE;
  l_action VARCHAR2(50);
  sql_text ora_name_list_t;
  v_stmt VARCHAR2(2000);
  n PLS_INTEGER;

BEGIN 
  IF (ora_dict_obj_name != 'SYS' AND ora_dict_obj_name != 'SYSTEM') THEN
    SELECT sys_context('USERENV', 'SESSIONID'), 
           sys_context('USERENV', 'IP_ADDRESS'), 
           sys_context('USERENV', 'HOST'), 
           sys_context('USERENV', 'MODULE'), 
           sys_context('USERENV', 'OS_USER'), 
           sys_context('USERENV', 'AUTHENTICATION_TYPE'), 
           sys_context('USERENV', 'SESSION_USER')
    INTO session_id, ip_addr, hostname, l_module, l_osuser, auth_type, l_session_user
    FROM dual;

    SELECT NAME, ASTATUS, LTIME , EXPTIME
    INTO user_name_, user_status_, user_datelock_, user_dateexp_  
    FROM user$ 
    WHERE NAME = ora_dict_obj_name;

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

    SELECT UPPER(SUBSTR(v_stmt, INSTR(v_stmt,' ',-1) + 1))
    INTO l_action
    FROM DUAL;

    IF (user_status_ = 16 AND l_action = 'LOCK') THEN 
      INSERT INTO sys.event_table VALUES 
      (sysdate, session_id, ip_addr, hostname, l_module, l_osuser, auth_type, ora_sysevent, ora_login_user, ora_database_name, 
      ora_dict_obj_name, ora_dict_obj_type, l_action);

    ELSIF (user_status_ = 16 AND l_action = 'EXPIRE') THEN
      INSERT INTO sys.event_table VALUES 
      (sysdate, session_id, ip_addr, hostname, l_module, l_osuser, auth_type, ora_sysevent, ora_login_user, ora_database_name, 
      ora_dict_obj_name, ora_dict_obj_type, l_action);  
    END IF;

  END IF;
END;
/
表sys.event_表:

create table event_table
(
event_datetime  date,
session_id VARCHAR2(30),
ip_addr VARCHAR2(30),
hostname VARCHAR2(100),
l_module VARCHAR2(100),
l_osuser VARCHAR2(30),
auth_type VARCHAR2(30),
l_ora_sysevent varchar2(20),
l_ora_login_user varchar2(30),
l_ora_database_name varchar2(50),
l_ora_dict_obj_name varchar2(30),
l_ora_dict_obj_type varchar2(20),
action varchar2(20)
)
/

在这件事上,我将不胜感激。

我终于找到了解决办法。利用oracle内部语法错误检查,以更合适的方式使用INSTR和SUBSTR,在使用正则表达式时克服了一些问题。 现在,它在alter命令中考虑了第n个空格、换行符或两者的混合

SUBSTR(上(v_stmt),(INSTR(RTRIM(上(v_stmt)),'LOCK')+1),4)

当然,在使用结果之前,您应该确保它的评估值不为1(表示未找到单词)


非常感谢大家的建设性意见,这些意见帮助我更接近解决方案。

也许,您可以尝试
upper(l\u action)=“LOCK”
或trim(upper(l\u action))=“LOCK”谢谢。试过了还是不好<代码>SQL>更改用户PERFSTAT帐户锁;操作:锁定用户。SQL>SQL>SQL>从sys.event_表中选择*;未选择行
不使用
修剪(上部(l_动作))=“锁定”
<代码>SQL>更改用户PERFSTAT帐户解锁;操作:解锁用户密码。SQL>更改用户PERFSTAT帐户锁;操作:锁定用户。SQL>从sys.event_表中选择*;未选择任何行如果不使用“选择…进入…来自双精度”,触发器的性能会更好。不需要那种构造;只需将值直接分配给变量: