patternMinor
Making a column unmodifiable/non-updatable after its row's initial creation?
Viewed 0 times
afternoncolumnitsunmodifiableinitialmakingcreationrowupdatable
Problem
What is the most idiomatic way to make a column unmodifiable/non-updatable after its initial creation via
Is there a constraint or technique that can easily be applied to the
I know I could hack the permissions to restrict writes to that table and that column and/or do some hacky triggers, updatable views, etc. Those solutions would not be maintainable because I have dozens of tables with columns that have this business logic requirement to be immutable and the database is already in production. I am not sure I might not be missing some low impact solution that is named something strange, because you know, Oracle.
Ideally I would like the
INSERT in 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
)Is there a constraint or technique that can easily be applied to the
crt_ts column that does not allow it to be modified on an UPDATE for a single user account.I know I could hack the permissions to restrict writes to that table and that column and/or do some hacky triggers, updatable views, etc. Those solutions would not be maintainable because I have dozens of tables with columns that have this business logic requirement to be immutable and the database is already in production. I am not sure I might not be missing some low impact solution that is named something strange, because you know, Oracle.
Ideally I would like the
crt_ts not to be INSERTable either and just force the default but that might be a stretch.Solution
GRANTS
Oracle has column level
Therefore, the answer you seek:
Don't
VPD/FGAC
Note: Virtual Private Database (VPD) and Fine Grain Access Control (FGAC) require Enterprise Edition (EE); 18c XE also supports VPD/FGAC
VPD allows you to add a
note: I haven't tested this code
TRIGGER
I wouldn't use
Oracle has column level
GRANT capabilities.Therefore, the answer you seek:
Don't
GRANT the update privilege on that column of that table to that user.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
Note: Virtual Private Database (VPD) and Fine Grain Access Control (FGAC) require Enterprise Edition (EE); 18c XE also supports VPD/FGAC
VPD allows you to add a
WHERE clause based specific conditions. In this example, the function always_false generates the appropriate conditions.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;
/note: I haven't tested this code
TRIGGER
I wouldn't use
TRIGGER to enforce this because triggers can be by-passed.Code Snippets
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;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;
/Context
StackExchange Database Administrators Q#224904, answer score: 3
Revisions (0)
No revisions yet.