虚拟列定义引用另一个虚拟列

时间:2016-03-18 14:23:08

标签: sql oracle oracle11g

是否可以拥有一个虚拟列,其列表达式定义引用另一个先前在表上定义的虚拟列? The documentation for column expressions说:

  

定义 column_expression 必须仅引用主题表中已定义的列,在当前语句或先前的语句中

这是我尝试做的一个简单示例,第三个虚拟列引用了已经定义的其他虚拟列:

create table numberManipulation
(
  value1 VARCHAR2 (10),
  Value2 VARCHAR2 (10),
  Addition AS  (DECODE (value1, 'late', 1, 0) + DECODE (value2, 'late', 1, 0)),
  subtraction AS(DECODE (value1, 'present', 1, 0) + DECODE (value2, 'present', 1, 0)),
  Compile AS (ADDITION + SUBTRACTION)
);

但这会出错:

ORA-54012: virtual column is referenced in a column expression

我正在尝试做什么?

1 个答案:

答案 0 :(得分:3)

不,虽然the documentation for column expressions没有明确表示你做不到。此限制显示在My Oracle Support文档466916.1中,并显示在create table documentation

  

AS子句中的column_expression具有以下限制:

     
      
  • 它不能通过名称引用另一个虚拟列   ...
  •   

您必须从第三个虚拟列中的每个虚拟列重复计算:

create table numberManipulation
(
  value1 VARCHAR2 (10),
  Value2 VARCHAR2 (10),
  Addition AS  (DECODE (value1, 'late', 1, 0) + DECODE (value2, 'late', 1, 0)),
  subtraction AS(DECODE (value1, 'present', 1, 0) + DECODE (value2, 'present', 1, 0)),
  Compile AS (DECODE (value1, 'late', 1, 0) + DECODE (value2, 'late', 1, 0)
    + DECODE (value1, 'present', 1, 0) + DECODE (value2, 'present', 1, 0))
);

Table NUMBERMANIPULATION created.

或稍微简单一点:

  Compile AS (DECODE (value1, 'late', 1, 'present', 1, 0)
    + DECODE (value2, 'late', 1, 'present', 1, 0))

...虽然您可能希望保留两个较长的表达式与早期的列匹配,以保持一致性和维护。

让一个虚拟列引用另一个虚拟列将决定它们必须被评估的顺序,并且可能导致循环依赖。

另一种方法是使用一个视图来计算基表中两个虚拟列的最终列:

create table numberManipulation
(
  value1 VARCHAR2 (10),
  Value2 VARCHAR2 (10),
  Addition AS  (DECODE (value1, 'late', 1, 0) + DECODE (value2, 'late', 1, 0)),
  subtraction AS(DECODE (value1, 'present', 1, 0) + DECODE (value2, 'present', 1, 0))
);

Table NUMBERMANIPULATION created.

create view vNumberManipulation as
select numberManipulation.*, addition + subtraction as compile
from numberManipulation;

View VNUMBERMANIPULATION created.

insert into numberManipulation (value1, value2) values ('late', 'late');
insert into numberManipulation (value1, value2) values ('late', 'present');
insert into numberManipulation (value1, value2) values ('present', null);
select * from vNumberManipulation;

VALUE1     VALUE2        ADDITION  SUBTRACTION      COMPILE
---------- ---------- ----------- ------------ ------------
late       late                 2            0            2
late       present              1            1            2
present                         0            1            1

视图也无法引用自己的列,因此您仍需要在基表中添加和减少。您还可以在视图上使用instead-of trigger,以便尝试修改视图实际上会更改基表,这会使其更加用户友好。