在oracle表中自动更改状态



我有两个表

user (user_id, username, status )

状态——比;(1 -主动,0 -被动)

user_work (user_work_id, user_id, status)

状态——比;(1 -主动,0 -被动)

如何自动设置用户表状态= 0如果在user_work对于某些用户,表没有活动状态。如果有user_work中的某些用户用户的激活状态表设置状态= 1

是否有可能使用触发器或使用其他解决方案,如调用一些过程?

从我的角度来看,这将是一个坏主意,因为您将status信息保存在两个表中(因此再见规范化)。如果你想知道某人的状态,可以查询。

示例表:

SQL> select * from t_user;
USER_ID USERNAM
---------- -------
1 Little
2 Foot
3 Pointer     --> doesn't have STATUS in USER_WORK
SQL> select * from user_work;
USER_WORK_ID    USER_ID     STATUS
------------ ---------- ----------
100          1          0
101          1          1   --> last status for USER_ID = 1 is 1
102          2          1   --> last (and only) status for USER_ID = 2 is 1
SQL>

查询(假设最后一个状态(按USER_WORK_ID降序排序)是某人的当前状态;如果USER_WORK表中没有行,则status =0)。

SQL> with temp as
2    (select w.user_id, w.status,
3            row_number() over (partition by w.user_id order by w.user_work_id desc) rn
4     from user_work w
5    )
6  select u.user_id, u.username, nvl(t.status, 0) status
7  from t_user u left join temp t on t.user_id = u.user_id
8                                and t.rn = 1;
USER_ID USERNAM     STATUS
---------- ------- ----------
1 Little           1
2 Foot             1
3 Pointer          0
SQL>

或者,一个简单的方法,创建一个视图:

SQL> create or replace view v_user_status as
2  with temp as
3    (select w.user_id, w.status,
4            row_number() over (partition by w.user_id order by w.user_work_id desc) rn
5     from user_work w
6    )
7  select u.user_id, u.username, nvl(t.status, 0) status
8  from t_user u left join temp t on t.user_id = u.user_id
9                                and t.rn = 1;
View created.
SQL> select * From v_user_status;
USER_ID USERNAM     STATUS
---------- ------- ----------
1 Little           1
2 Foot             1
3 Pointer          0
SQL>

我认为你可以通过statement trigger实现这一点,这样的东西应该服务于目的。当然,您应该从一个清理点开始,这意味着首先您需要用user_work表的最新状态更新user表中的所有值。

我也相信@Littlefoot语句是正确的,在两个表中保留相同的字段从来都不是一个好主意。

我在这里给你的是一个解决方案,通过在user_work表中更改或添加新条目来维护用户表中的状态。我想这就是你要的。

让我们想象一下这个场景(我对表使用了不同的名称)

SQL> create table user_names ( user_id number, username varchar2(1) , status varchar2(1) ) ;
Table created.
SQL> insert into user_names values ( 1 , 'A' , 1 );
1 row created.
SQL> insert into user_names values ( 2 , 'B' , 1 );
1 row created.
SQL> create table user_work ( user_work_id number, user_id number, status varchar2(1) ) ;
Table created.

在这个场景中,user_work表中还没有行,所以让我们创建语句触发器来更新或插入

SQL> create or replace trigger upd_status_user 
after insert or update on user_work
begin 
merge into user_names t 
using ( select * from user_work ) s 
on ( t.user_id = s.user_id ) 
when matched then 
update set t.status = s.status 
where 
s.user_work_id = ( select max(user_work_id) from user_work s where t.user_id = s.user_id ) ;
end;
/
Trigger created.
SQL>

现在我们测试它

SQL> insert into user_work values ( 100 , 1 , 1 );
1 row created.
SQL> commit ;
Commit complete.
SQL> select * from user_names ;
USER_ID U S
---------- - -
1 A 1
2 B 1
SQL> insert into user_work values ( 101 , 1 , 0 );
1 row created.
SQL> commit ;
Commit complete.
SQL> select * from user_names ;
USER_ID U S
---------- - -
1 A 0
2 B 1
SQL> insert into user_work values ( 102 , 1 , 1 ) ;
1 row created.
SQL> commit ;
Commit complete.
SQL>  select * from user_names ;
USER_ID U S
---------- - -
1 A 1
2 B 1

当我在user_work表中插入新记录时,您可以看到user_names表(您的用户表)中的变化,保持最新状态。

如果我更新,它会发生相同的

SQL> update user_work set status = 0 where user_work_id=102 ;
1 row updated.
SQL> commit ;
Commit complete.
SQL> select * from user_names ;
USER_ID U S
---------- - -
1 A 0
2 B 1

一个选择,如果时间不是很棘手,你可以创建一个作业,每小时检查一次,并设置状态,像这样:

BEGIN
DBMS_SCHEDULER.CREATE_JOB(JOB_NAME        => 'job_name',
JOB_TYPE        => 'PLSQL_BLOCK',
JOB_ACTION      => 'BEGIN
UPDATE USER
SET STATUS = 0
WHERE USER_ID NOT IN (SELECT USER_ID FROM USER_WORK W WHERE STATUS = 1);
COMMIT;
END;',
START_DATE      => SYSTIMESTAMP,
REPEAT_INTERVAL => 'freq=hourly; byminute=0; bysecond=0;',
ENABLED         => TRUE);
END;

注意:你也可以使用触发器,但在我看来,状态应该存储在一个地方,应该在需要时直接更新特定的操作

所以,你提供了几乎所有可能的选择,除了一个我相信。如果您无法按照Littlefoot的答案进行操作,您可以尝试使用虚拟列。

  1. 创建user_work table:

    create table user_work(user_work_id number, user_id number, status number);
    
  2. 创建计算用户状态的存储函数:

    create or replace function get_status(p_user_id number) return number deterministic
    is
    active_cnt number := 0;
    begin
    select count(1)
    into active_cnt
    from user_work uw
    where uw.user_id = p_user_id;
    if active_cnt > 0 then
    return 1;
    else
    return 0;
    end if;
    end;
    
  3. 创建表user_tab:

    create table user_tab(user_id number, status generated always as (get_status(user_id)) virtual);
    

现在,让我们测试一下:

insert into user_tab(user_id) values(1);
insert into user_tab(user_id) values(2);
insert into user_work(user_work_id, user_id, status) values(1, 1, 1);
select * from user_tab;
<表类>user_id状态tbody><<tr>1120

最新更新