Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使数据库列不可编辑_Sql_Oracle - Fatal编程技术网

Sql 使数据库列不可编辑

Sql 使数据库列不可编辑,sql,oracle,Sql,Oracle,如何使SQL数据库列不可编辑 我希望能够插入,但在更新时,该列不应被允许更改 我知道这可以通过在更新时使用触发器来实现,但是还有更优雅的解决方案吗 最好使用Entity Framework Core或Oracle,但我对任何用于教育目的的技术都感兴趣。没有用于固定列值的声明机制。唯一的方法是使用触发器以编程方式执行。触发器使我们能够在更新事件期间比较列的:old和:new值,并在它们不同时采取措施 以下是最直接的方法: create or replace trigger trg23 before

如何使SQL数据库列不可编辑

我希望能够插入,但在更新时,该列不应被允许更改

我知道这可以通过在更新时使用触发器来实现,但是还有更优雅的解决方案吗


最好使用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;
    /