如果 <table> 具有虚拟列,是否(以及如何)在 Oracle 中“插入到 <table> 值 <rowtype-variable>”

Ren*_*ger 4 oracle oracle-11g-r2 insert virtual-columns

这是一张桌子

create table tq84_virtual_test_without (
  col_1 number,
  col_2 number,
  col_3 number,
  col_4 number,
  col_5 number
);
Run Code Online (Sandbox Code Playgroud)

规则col_5的值是其他四列的总和。

所以表格被相应地填充:

insert into tq84_virtual_test_without values( 1, 2, 3, 4, 10);
insert into tq84_virtual_test_without values( 3, 8, 7, 5, 23);

commit;
Run Code Online (Sandbox Code Playgroud)

现在,假设需要复制一行并更改列的值。这当然可以非常优雅地完成(恕我直言,也就是说)使用rowtype-variable,就像这样

declare
  r tq84_virtual_test_without%rowtype;
begin

  select * into r from tq84_virtual_test_without where col_2 = 8;

  r.col_4 := r.col_4 - 2;
  r.col_5 := r.col_5 - 2;

  insert into tq84_virtual_test_without values r;

end;
/
Run Code Online (Sandbox Code Playgroud)

这很优雅,因为它不会用insert into ... (col_1, col_2...) values (.., ..)语句使源代码混乱,如果可能的话,我想保留此功能。

另一方面,col_5虚拟列的完美候选者。所以,这里几乎是一样的,但col_5作为一个虚拟列:

create table tq84_virtual_test_with (
  col_1 number,
  col_2 number,
  col_3 number,
  col_4 number,
  col_5 as (col_1 + col_2 + col_3 + col_4) virtual
);

insert into tq84_virtual_test_with values( 1, 2, 3, 4, default);
insert into tq84_virtual_test_with values( 3, 8, 7, 5, default);

commit;
Run Code Online (Sandbox Code Playgroud)

现在,不幸的是,以下构造不再起作用:

declare
  r tq84_virtual_test_with%rowtype;
begin

  select * into r from tq84_virtual_test_with where col_2 = 8;

  r.col_4 := r.col_4 - 2;

--     
--  ORA-54013: INSERT operation disallowed on virtual columns
--
  insert into tq84_virtual_test_with values r;

end;
/
Run Code Online (Sandbox Code Playgroud)

那么,这是否仍然可以(如果可以,如何)将这个行类型变量虚拟列一起使用?

Phi*_*lᵀᴹ 11

使用排除虚拟列的视图进行操作。我刚刚测试了这个并且它有效:

create view v_tq84_virtual_test_with as ( select col_1, col_2, col_3, col_4 from tq84_virtual_test_with );

declare
  r v_tq84_virtual_test_with%rowtype;
begin

  select * into r from v_tq84_virtual_test_with where col_2 = 8;

  r.col_4 := r.col_4 - 2;

  insert into v_tq84_virtual_test_with values r;

end;
/
Run Code Online (Sandbox Code Playgroud)

据我所知,这是解决您使用 %rowtype 的要求的唯一方法。