我有兩張桌子
user (user_id, username, status )
狀態 -->(1 - 主動,0 - 被動)
user_work (user_work_id, user_id, status)
狀態 -->(1 - 主動,0 - 被動)
如果在user_work表中某些用戶沒有活動狀態,則如何在用戶表 status = 0 中自動設定。如果用戶表中的某個用戶處于user_work活動狀態,則設定 status = 1
是否可以使用觸發器或使用其他解決方案,例如呼叫某個程式?
uj5u.com熱心網友回復:
從我的角度來看,這將是一個壞主意,因為您將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>
uj5u.com熱心網友回復:
我認為您可以通過 來實作這一點statement trigger,這樣的事情應該可以達到目的。當然,你應該從清理點開始,這意味著首先你需要用user表的最新狀態更新表中的所有值user_work。
我也相信@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
uj5u.com熱心網友回復:
一種選擇,如果時間不是很棘手,您可以創建一個作業來每小時檢查一次并設定如下狀態:
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;
注意:您也可以使用觸發器,但在我看來,狀態應該存盤在一個地方,并且應該在需要時直接更新特定操作
uj5u.com熱心網友回復:
所以,除了我相信的一個選項之外,你幾乎可以選擇所有可能的選項。如果您不適合遵循 Littlefoot 的回答,您可以嘗試使用虛擬列。
創建 user_work 表:
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;
| 用戶身份 | 地位 |
|---|---|
| 1 | 1 |
| 2 | 0 |
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/327528.html
