Oracel用户定义的函数始终返回NULL

时间:2017-05-25 13:36:52

标签: oracle

我试图在oracle中编写UDF,根据提供的日期和今天之间的差异返回一些。以下是我的代码

SELECT FN_AGE_RANGE('01.01.2017') FROM DUAL;

CREATE OR REPLACE FUNCTION FN_AGE_RANGE(
    SAP_DATE IN VARCHAR2 )
  RETURN VARCHAR2
IS
  ResultVar VARCHAR2(255);
    TheDate DATE;
    TheDiff NUMBER;
  BEGIN
    --convert to date
    SELECT
      CASE
        WHEN SAP_DATE = '00.00.0000'
        THEN NULL
        ELSE to_date(SAP_DATE,'dd.mm.yyyy')
      END
    INTO TheDate
    FROM DUAL;
    --workout date difference
    SELECT sysdate - TheDate
    INTO TheDiff
    FROM DUAL;
    --set the frequency
    SELECT
      CASE
        WHEN TheDiff < -180
        THEN '>6 Months'
        WHEN TheDiff < -90
        THEN '3-6 Months'
        WHEN TheDiff < 0
        THEN '<3 Months'
      END
    INTO ResultVar
    FROM DUAL;
    RETURN(ResultVar);
  END;

3 个答案:

答案 0 :(得分:2)

代码

(sysdate - TheDate)是积极的,所以

SELECT


CASE
    WHEN TheDiff < -180
    THEN '>6 Months'
    WHEN TheDiff < -90
    THEN '3-6 Months'
    WHEN TheDiff < 0
    THEN '<3 Months'
  END
INTO ResultVar
FROM DUAL;

总是会返回null

将代码的最后一部分更改为此

SELECT


    CASE
        WHEN TheDiff > -180
        THEN '>6 Months'
        WHEN TheDiff > -90
        THEN '3-6 Months'
        WHEN TheDiff > 0
        THEN '<3 Months'
      END
    INTO ResultVar
    FROM DUAL;

答案 1 :(得分:1)

Vecchiasignora的回答与您的代码逻辑正确相关。但是,我想添加它来运行case语句,你不需要SQL,你也可以在PL / SQL中使用该构造。这样可以简化您的代码。

    CREATE OR REPLACE FUNCTION FN_AGE_RANGE(
        SAP_DATE IN VARCHAR2 )
      RETURN VARCHAR2
    IS
      ResultVar VARCHAR2(255);
        TheDate DATE;
        TheDiff NUMBER;
      BEGIN
        --convert to date
         CASE
            WHEN SAP_DATE = '00.00.0000' THEN NULL;
            ELSE TheDate := to_date(SAP_DATE,'dd.mm.yyyy');
          END CASE;

        --workout date difference
        TheDiff :=  sysdate - TheDate;

        --set the frequency
          CASE
            WHEN TheDiff > 180 THEN ResultVar := '>6 Months';
            WHEN TheDiff > 90  THEN ResultVar := '3-6 Months';
            WHEN TheDiff > 0   THEN ResultVar := '<3 Months';
          END CASE;

        RETURN(ResultVar);
      END;

答案 2 :(得分:0)

确保您的案例陈述涵盖您的样本集

首先,SAP_DATE的显着值似乎是SYSDATE大于SAP_DATE时。

例如,当我们有2016年11月1日的日期时,SAP_DATE的年龄应为6个月。

SAP_DATE大于当前日期时,未定义ResultVar。我将其称为“当前”。

在Oracle中使用case语句时,重要的是要考虑正在执行短路评估,因此第一个布尔表达式为true将是分配给ResultVar的结果值。

以下是我的修改:

SCOTT@dev>set echo on;
SCOTT@dev>CREATE OR REPLACE FUNCTION FN_AGE_RANGE(
  2      SAP_DATE IN VARCHAR2 )
  3    RETURN VARCHAR2
  4  IS
  5    ResultVar VARCHAR2(255);
  6      TheDate DATE;
  7      TheDiff NUMBER;
  8    BEGIN
  9      --convert to date
 10      SELECT
 11        CASE
 12          WHEN SAP_DATE = '00.00.0000'
 13          THEN NULL
 14          ELSE to_date(SAP_DATE,'dd.mm.yyyy')
 15        END
 16      INTO TheDate
 17      FROM DUAL;
 18      --workout date difference
 19      SELECT sysdate - TheDate
 20      INTO TheDiff
 21      FROM DUAL;
 22      --set the frequency
 23      SELECT
 24        CASE
 25          WHEN TheDiff > 180
 26          THEN '>6 Months'
 27          WHEN TheDiff > 90
 28          THEN '3-6 Months'
 29          WHEN TheDiff > 0
 30          THEN '<3 Months'
 31          WHEN TheDiff <= 0
 32          THEN  'Current'
 33          ELSE NULL
 34        END
 35      INTO ResultVar
 36      FROM DUAL;
 37      RETURN(ResultVar);
 38    END;
 39  /

Function FN_AGE_RANGE compiled

SCOTT@dev>---sample data
SCOTT@dev>-- > 6 months
SCOTT@dev>SELECT FN_AGE_RANGE('01.11.2016') FROM DUAL;
FN_AGE_RANGE('01.11.2016')
>6 Months


SCOTT@dev>-- > 3 months
SCOTT@dev>SELECT FN_AGE_RANGE('01.02.2017') FROM DUAL;
FN_AGE_RANGE('01.02.2017')
3-6 Months


SCOTT@dev>SELECT FN_AGE_RANGE('01.07.2017') FROM DUAL;
FN_AGE_RANGE('01.07.2017')
Current


SCOTT@dev>--> NULL
SCOTT@dev>SELECT FN_AGE_RANGE(NULL) FROM DUAL;
FN_AGE_RANGE(NULL)