Oracle
在行的初始創建後使列不可修改/不可更新?
INSERT
通過在 Oracle 中初始創建列後,使列不可修改/不可更新的最慣用方法是什麼?CREATE TABLE my_table ( id NUMBER NOT NULL CONSTRAINT my_table_pk PRIMARY KEY, -- lots of other columns that are updatable crt_ts TIMESTAMP(6) NOT NULL default CURRENT_TIMESTAMP, -- immutable? upd_ts TIMESTAMP(6) NOT NULL )
是否存在可以輕鬆應用於
crt_ts
不允許UPDATE
針對單個使用者帳戶對其進行修改的列的約束或技術。我知道我可以破解權限以限制對該表和該列的寫入和/或執行一些 hacky 觸發器、可更新視圖等。這些解決方案將無法維護,因為我有幾十個表,其中包含具有此業務邏輯要求的列是不可變的,並且數據庫已經在生產中。我不確定我可能不會錯過一些被命名為奇怪的低影響解決方案,因為你知道,Oracle。
理想情況下,我希望兩者
crt_ts
都不能INSERT
,只是強制預設,但這可能是一個延伸。
贈款
Oracle 具有列級
GRANT
功能。因此,您尋求的答案是:不要
GRANT
將該表的該列的更新權限授予該使用者。grant insert,select,delete on my_table to some_role; grant update (updatable_column, upd_ts) on my_table to some_role; grant some_role to single_user;
VPD/FGAC
注意:虛擬私有數據庫(VPD)和細粒度訪問控制(FGAC)需要企業版(EE);18c XE 還支持 VPD/FGAC
VPD 允許您添加
WHERE
基於特定條件的子句。在此範例中,該函式always_false
生成適當的條件。create function always_false return varchar2 deterministic as begin if sys_context('USERENV', 'SESSION_USER' ) = 'SINGLE_USER' then return '1=0' end if; return null; -- does not apply a rule end; / begin dbms_rls.add_policy ( object_name => 'MY_TABLE' ,policy_name => 'NO_CRT_TS' ,policy_function => 'ALWAYS_FALSE' ,statement_types => 'UPDATE' ,enable => 'TRUE' ,static_policy => 'TRUE' ,sec_relevent_cols => 'CRT_TS' ); end; /
注意:我沒有測試過這段程式碼
扳機
我不會
TRIGGER
用來強制執行此操作,因為可以繞過觸發器。