0

我正在尝试使用触发器计算用户登录数据库的总时间,我的表结构如下所示:

create table stats$user_log
(
   user_id           varchar2(30),
   session_id           number(8),
   host              varchar2(30),
   logon_day                 date,
   logon_time        varchar2(10),
   logoff_day                date,
   logoff_time       varchar2(10),
   elapsed_minutes       varchar2(32)
);

我的登录触发器如下:

create or replace trigger
   logon_audit_trigger
AFTER LOGON ON DATABASE
BEGIN
insert into stats$user_log values(
   user,
   sys_context('USERENV','SESSIONID'),
   sys_context('USERENV','HOST'),
   sysdate,
   to_char(sysdate, 'hh24:mi:ss'),
   null,
   null,
   null
);
END;
/

我的注销触发器如下:

create or replace trigger
   logoff_audit_trigger
BEFORE LOGOFF ON DATABASE
BEGIN
UPDATE
    stats$user_log
set

      logoff_day = sysdate,
      logoff_time = to_char(sysdate, 'hh24:mi:ss'),
      elapsed_minutes = round((logoff_day - logon_day)*1440,2)

  WHERE
   sys_context('USERENV','SESSIONID') = session_id;
END;
/

当用户注销时,除了 elapse_minutes 列之外的所有内容都被捕获,它保持为空。

谁能告诉我哪里出错了,谢谢

4

2 回答 2

0

在您进行更新时,logoff_day您在表达式右侧引用的set仍然为 null,因此表达式的计算结果为 null。

您引用的任何列值都必须是更新前的值,或者更改在子句中分配列的顺序set会改变更新的工作方式,这充其量是令人困惑的。根据旧值设置列的更新 - 例如set salary = salary * 1.1- 会特别成问题。

您可以参考sysdate第二次:

  logoff_day = sysdate,
  logoff_time = to_char(sysdate, 'hh24:mi:ss'),
  elapsed_minutes = round((sysdate - logon_day)*1440,2)
于 2013-03-31T22:32:39.497 回答
0

如果启用了会话审核,则数据库已经为您执行此操作。为什么要为自己创造呢?检查 dba_audit_session 以获取结果。您可能需要与您的 dba / 安全人员交谈以获得访问权限,但这可能是值得的。

于 2013-04-01T10:24:09.997 回答