【问题标题】:ORACLE 11g TriggerORACLE 11g 触发器
【发布时间】:2017-07-19 23:47:29
【问题描述】:

我正在使用下面的 alter 语句测试名为“tulockout”的触发器...“alter user testuser account lock;”查看触发器日志是否记录了表“log_table_changes”中发生的事情。 但是,某些值没有准确地记录到表“log_table_changes”中。具体来说,v_dusr.start_dt 在触发时返回 NULL,在我执行“alter user testuser account lock;”后会触发“tulockout”。声明。

我不确定为什么。你能帮忙吗? 我该如何解决这个问题?谢谢。

create or replace trigger tulockout 
after alter on schema 

declare

cursor v_abc is
    select du.username, max(us.start_dt)
    from dba_users du, user_session us, users_info ui
    where ui.db_user_name = du.username
      and ui.db_user_name = us.user_name
      and ui.db_user_name = ora_login_user;

v_dusr  v_abc%ROWTYPE; 

begin

  if(ora_sysevent = 'ALTER' and v_dusr.username = ora_dict_obj_name and
v_dusr.account_status = 'LOCKED') then

  insert into log_table_changes(username,
                                lastlogin_date,
                                notes,
                                execute_date,
                                script_name
                               ) 
                         values(
                                v_dusr.username,
                                v_dusr.start_dt,
                                ora_dict_obj_type||', '||
                                ora_dict_obj_name||' has been locked out.',
                                sysdate,
                                ora_sysevent
                               );
end;

【问题讨论】:

    标签: oracle11g triggers


    【解决方案1】:

    您正在声明一个游标,以及基于该游标的记录;但您永远不会执行游标查询或填充变量。

    您的游标查询当前缺少 group-by 子句,因此在运行时会出错,因为聚合函数。不过,您实际上并不需要在选择列表中包含用户名,因为您已经知道该值。不过,您稍后会引用 v_duser.account_status 字段,该字段在您的游标查询/行类型中不存在,因此您也需要添加(和分组依据)。

    触发器还需要在数据库级别,而不是架构级别;并且除非您打算记录谁执行了 alter 命令,否则您不必参考 ora_login_user - 查看 用户的状态似乎不是很有帮助。

    你根本不需要光标;一个 select-into 会做,比如(假设总会有一行从连接返回到您的 user_session 和 users_info 表;这意味着它们以与 dba_users 相同的情况存储用户名 - 尽管我不确定你为什么正在加入 users_info 吗?):

    create or replace trigger tulockout 
    after alter on database
    declare    
      v_start_dt user_session.start_dt%TYPE;
      v_account_status dba_users.account_status%TYPE;
    begin   
      select du.account_status, max(us.start_dt)
      into v_account_status, v_start_dt
      from dba_users du
      join user_session us on us.db_user_name = du.username
      -- join not needed?
      -- join users_info ui on ui.db_user_name = us.user_name
      where du.username = ora_dict_obj_name
      group by du.account_status;
    
      if(ora_sysevent = 'ALTER' and ora_dict_obj_type = 'USER'
          and v_account_status = 'LOCKED') then
        insert ...
    

    然后在插入中使用这些日期和状态变量以及ora_dict_obj_name(被更改的用户)。

    我还改用了现代连接语法,并稍微调整了条件。

    未经测试,但应该会给你这个想法。

    您可以通过对这些表执行单个 insert ... select 来简化操作,从而无需局部变量。

    【讨论】:

    • 感谢您的回复。我测试了您的答案,但没有将任何内容添加到“log_table_changes”表中。我是否有“在架构上更改后创建或替换触发器 tulockout”正确,因为触发器应该处理 dba_users 表 status_Account 列从 OPEN 更改为 LOCKED。
    • 您的问题暗示触发器正在工作,尽管插入了一些空值;但再看一遍,我认为不可能。我认为它必须是数据库触发器,而不是模式?只有当用户锁定自己的帐户时,这两个 ora_ 变量才会匹配 - 我认为......目前无法测试。
    猜你喜欢
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    相关资源
    最近更新 更多