PL / SQL Триггер не оценивает состояние ПЧ, как ожидалось - PullRequest
0 голосов
/ 21 апреля 2020

Я с трудом пытаюсь заставить этот маленький кусочек пл / sql работать! Если кто-то может понять, что на самом деле блокирует? Цель сценария - проверить действия DDL alter user, приводящие к истечению или блокировке учетной записи.

Я попытался отладить его с помощью dbms_output.put_line, и кажется, что IF (user_status_ = 16 AND l_action = 'LOCK') не имеет значения ИСТИНА. Скорее всего, это проблема с переменной l_action, потому что, когда я ее удаляю, она регистрирует что-то в таблице, когда встречается cond user_status_ = 16.

Однако, если я распечатаю l_action с dbms_output.put_line('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_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)
)
/

Буду признателен за любую помощь в этом вопросе.

1 Ответ

1 голос
/ 22 апреля 2020

В конце концов я нашел способ обойти. Использовал внутреннюю проверку синтаксических ошибок oracle и использовал INSTR и SUBSTR более подходящим способом, чтобы преодолеть несколько проблем при использовании регулярных выражений. теперь он принимает во внимание n-й пробел, разрыв строки или их сочетание в команде alter.

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

конечно, вы должны убедиться, что он не равен 1 (имеется в виду слово не найдено) ) перед использованием результатов.

Большое спасибо всем вам за ваши конструктивные комментарии, которые очень помогают мне приблизиться к решению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...