PL/SQL 触发器未按预期评估 IF 条件
PL/SQL Trigger not evaluating IF condition as expected
我在尝试完成 pl/sql 这一小块工作时遇到了一些困难!
如果有人能弄清楚到底是什么阻塞了?
该脚本的目的是审核导致帐户过期或锁定的 DDL alter user
操作。
我尝试用 dbms_output.put_line
调试它,它似乎没有将 IF (user_status_ = 16 AND l_action = 'LOCK')
评估为 TRUE。最有可能是变量 l_action
的问题,因为当我删除它时,它确实在满足条件 user_status_ = 16 时在 table 中记录了一些内容。
但是,如果我用 dbms_output.put_line('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;
/
table sys.event_table :
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)
)
/
我将不胜感激在这件事上的任何帮助。
我终于找到了 around.took oracle 内部语法错误检查的优势,并以更合适的方式使用 INSTR 和 SUBSTR 来克服使用正则表达式时的一些问题。
它现在在 alter 命令中考虑了第 n 个 space、换行符或两者的混合。
SUBSTR(UPPER(v_stmt),(INSTR(RTRIM(UPPER(v_stmt)),' LOCK') +1),4)
当然,在使用结果之前,您应该确保它的计算结果不为 1(意思是未找到单词)。
非常感谢大家的建设性意见,这些意见帮助我更接近解决方案。
我在尝试完成 pl/sql 这一小块工作时遇到了一些困难!
如果有人能弄清楚到底是什么阻塞了?
该脚本的目的是审核导致帐户过期或锁定的 DDL alter user
操作。
我尝试用 dbms_output.put_line
调试它,它似乎没有将 IF (user_status_ = 16 AND l_action = 'LOCK')
评估为 TRUE。最有可能是变量 l_action
的问题,因为当我删除它时,它确实在满足条件 user_status_ = 16 时在 table 中记录了一些内容。
但是,如果我用 dbms_output.put_line('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;
/
table sys.event_table :
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)
)
/
我将不胜感激在这件事上的任何帮助。
我终于找到了 around.took oracle 内部语法错误检查的优势,并以更合适的方式使用 INSTR 和 SUBSTR 来克服使用正则表达式时的一些问题。 它现在在 alter 命令中考虑了第 n 个 space、换行符或两者的混合。
SUBSTR(UPPER(v_stmt),(INSTR(RTRIM(UPPER(v_stmt)),' LOCK') +1),4)
当然,在使用结果之前,您应该确保它的计算结果不为 1(意思是未找到单词)。
非常感谢大家的建设性意见,这些意见帮助我更接近解决方案。