Sql 使数据库列不可编辑
如何使SQL数据库列不可编辑 我希望能够插入,但在更新时,该列不应被允许更改 我知道这可以通过在更新时使用触发器来实现,但是还有更优雅的解决方案吗Sql 使数据库列不可编辑,sql,oracle,Sql,Oracle,如何使SQL数据库列不可编辑 我希望能够插入,但在更新时,该列不应被允许更改 我知道这可以通过在更新时使用触发器来实现,但是还有更优雅的解决方案吗 最好使用Entity Framework Core或Oracle,但我对任何用于教育目的的技术都感兴趣。没有用于固定列值的声明机制。唯一的方法是使用触发器以编程方式执行。触发器使我们能够在更新事件期间比较列的:old和:new值,并在它们不同时采取措施 以下是最直接的方法: create or replace trigger trg23 before
最好使用Entity Framework Core或Oracle,但我对任何用于教育目的的技术都感兴趣。没有用于固定列值的声明机制。唯一的方法是使用触发器以编程方式执行。触发器使我们能够在更新事件期间比较列的
:old
和:new
值,并在它们不同时采取措施
以下是最直接的方法:
create or replace trigger trg23 before update on t23 for each row
begin
if :old.col1 <> :new.col1 then
raise_application_error(-20000, 'You cannot change COL1!');
end if;
end;
/
通过在触发器规范中指定列名,我们可以使触发器主体真正简洁。这是我们能得到的最接近优雅的
触发器还使我们能够无声地抑制更改。这似乎是一个很有吸引力的选择,因为它遵循unix模型,只在真正异常的情况下引发异常。但根据我的经验,当计算机在没有解释的情况下“丢失”更改时,用户可能会感到困惑
create or replace trigger trg23 before update on t23 for each row
begin
:new.col1 := :old.col1;
end;
/
下面是这些触发器中的一个
上面的答案假设我们的用户可以为原始值插入任何内容,但由于某些特殊的业务原因,无法更改它。但是如果列必须是不可变的,因为它的值是固定的或派生的,那么您可能需要一个虚拟列 此表对子类型列具有固定值:
create table t69 (id number primary key
, subtype varchar2(4) generated always as ('ACCT')
, credit_limit number )
/
我们无法更新子类型:
update t69
set subtype = 'CUST'
where id = 1234
/
这是在逻辑模型中实现超类型/子类型实体的有用构造
虚拟列还可用于提供用户友好的智能钥匙,同时保持第一个标准形式。此示例显示了如何从其组成部分派生业务密钥事件_REF:
create table t42 (deptid varchar2(2) not null
, create_dt date not null
, serial_no number not null
, event_ref varchar2(32) generated always as (deptid || '\' || to_char(create_dt, 'yyyymm') || '\' || to_char(serial_no, 'fm0000000'))
)
/
我认为这类需求的最佳解决方案是VPD(虚拟专用数据库),因为您不想使用触发器 通过在表上应用
VPD
,您将能够将透明where子句添加到任何类型的语句中
假设您的表名为MY\u table
,且不可更新的列名为MY\u COL
,则只需使用函数在表上创建VPD
,如下所示:
create function my_table_vpd_fun return varchar2 deterministic
as
return '1=0';
end;
/
begin
dbms_rls.add_policy (
object_name => 'MY_TABLE' -- your table name goes here
,policy_name => 'MY_TABLE_UPDATE_VPD'
,policy_function => 'MY_TABLE_VPD_FUN'
,statement_types => 'UPDATE'
,static_policy => 'TRUE'
,sec_relevent_cols => 'MY_COL' -- your column name goes here
);
end;
/
每当MY\u表
的UPDATE
中使用MY\u COL
时,此VPD
将应用1=0
条件。因此,整个声明不会更新任何内容(对您来说可能是个坏消息)。如果update语句中未引用MY_COL
,则此VPD
将不适用where
条件,并允许对任何其他列进行更新
但是,如果符合您的需求,VPD
概念是很好的
干杯
确保应用程序不直接连接到表的所有者,而是让他们连接到单独的用户(例如,APP
)
在表上创建可更新的视图。将视图上的SELECT/INSERT/UPDATE/DELETE(根据需要)授予APP
在视图上创建一个INSTEAD OF触发器,以将插入、更新和删除转换为基础表。触发器中的PL/SQL可以忽略该列以进行更新,如果希望它检测到修改该列的尝试,则可以引发异常
那么,您正在使用的是Oracle吗?EF core与OracleYou能否提供有关您试图实施的业务规则的更多详细信息?为什么要选择不可变列?并不是说这是一个不合理的要求,只是如果我们了解您试图解决的问题,那么提供答案会更容易。
create function my_table_vpd_fun return varchar2 deterministic
as
return '1=0';
end;
/
begin
dbms_rls.add_policy (
object_name => 'MY_TABLE' -- your table name goes here
,policy_name => 'MY_TABLE_UPDATE_VPD'
,policy_function => 'MY_TABLE_VPD_FUN'
,statement_types => 'UPDATE'
,static_policy => 'TRUE'
,sec_relevent_cols => 'MY_COL' -- your column name goes here
);
end;
/