我有两个表
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的答案进行操作,您可以尝试使用虚拟列。
-
创建user_work table:
create table user_work(user_work_id number, user_id number, status number);
-
创建计算用户状态的存储函数:
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;
-
创建表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;