Oracle

在行的初始創建後使列不可修改/不可更新?

  • December 14, 2018

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用來強制執行此操作,因為可以繞過觸發器。

引用自:https://dba.stackexchange.com/questions/224904