在oracle虚拟列中进行Sysdate

时间:2017-06-15 07:14:05

标签: sql oracle

我正在尝试在oracle中创建一个使用case语句的虚拟列但是如果我调用SYSDATE函数它会给我这个错误:

ORA-54002: only pure functions can be specified in a virtual column expression

这是查询:

alter table t_requirements ADD
  REQUIREMENT_STATE varchar2(30)
  generated always as(
    CASE
     WHEN t_requirements.activation_date- SYSDATE - 5 <= 0 AND 
       t_requirements.activation_date - SYSDATE > 0 THEN 'Exist'
     WHEN t_requisiti.activation_date - SYSDATE <=0 THEN 'Active'
    END) virtual;

3 个答案:

答案 0 :(得分:6)

您正在使用SYSDATE来构建虚拟列。这是不允许的,因为SYSDATE不是确定性的,即它并不总是返回相同的值。想象一下,您在此列上构建索引。一秒钟后,索引已经无效了!

您似乎应该编写一个包含此ad hoc计算列的视图

答案 1 :(得分:3)

sysdate不具有确定性。它的值每次运行时都会有所不同。虚拟列必须是确定性的。否则会出现奇怪的情况,即查询记录会改变其价值。相当正确的Oracle不允许这样做。

在这种情况下,我们仍然需要使用查询(可能作为表格的视图)来显示派生值。

select r.*
     , cast(
       CASE
          WHEN r.activation_date- SYSDATE - 5 <= 0 AND 
               r.activation_date - SYSDATE > 0 THEN 'Exist'
          WHEN r.activation_date - SYSDATE <=0 THEN 'Active'
          else 'Inactive'
       END 
       as  varchar2(30)) as REQUIREMENT_STATE
from requirements r
;

顺便提一下,您的CASE声明是否需要ELSE?在activation_date大于SYSDATE + 5

时显示空白以外的内容

答案 2 :(得分:1)

您可以使用SYSDATE来支持虚拟列。在查询时计算虚拟列。如果您创建一个函数ISACTIVE_FROM_TO,例如:

CREATE OR REPLACE FUNCTION ISACTIVE_FROM_TO (p_active_from IN DATE, p_active_to IN DATE)
    RETURN number
    DETERMINISTIC
IS

BEGIN
    RETURN (CASE WHEN SYSDATE BETWEEN NVL (p_active_from, SYSDATE) AND NVL (p_active_to, SYSDATE) THEN 1 ELSE 0 END);

EXCEPTION
    WHEN OTHERS THEN
        RAISE VALUE_ERROR;
END;
/

在具有ACTIVE_FROM和ACTIVE_TO日期列的表上定义您的虚拟列:

alter table xyz
  add ISACTIVE NUMBER(1) 
   GENERATED ALWAYS AS (ISACTIVE_FROM_TO"(ACTIVE_FROM,ACTIVE_TO));

该表将根据sysdate动态计算值。该函数是确定性的...给出相同的from / to date和sysdate它将始终返回相同的值。该函数需要具有确定性关键字。

当sysdate接近ACTIVE_TO日期/时间时,表的连续查询将导致ISACTIVE值从1变为0 ....因为该函数根据移动SYSDATE计算值。操作与单独的视图非常相似。