【问题标题】:ORACLE-SQL: Function, how to detect a null selection and return 0ORACLE-SQL:函数,如何检测空选择并返回0
【发布时间】:2021-04-25 01:00:47
【问题描述】:

我写了以下函数。但最后我无法在 count 为空时检测到它并放入返回 0 的 result 变量;不知道怎么回事,可能count(*)应该是外部SELECT放的,不确定。

运行为例,随机输入:

SELECT is_department_active('44','222') from dual

我得到了 is_department_active (null) 但预期为 0。

 CREATE OR REPLACE FUNCTION is_department_active (
        department_id   VARCHAR2,
        doc_id      VARCHAR2
    ) RETURN NUMBER IS
        result NUMBER(1);  
        cnt number(3);
    BEGIN
    result:=0;
        SELECT
            dep_active, count(*)
        INTO result,cnt
        FROM
            (
           SELECT
            grade,
            dep_active,  3 "priority number"
        FROM
            vrsc.inst_department
        WHERE
            af_feature_id = department_id
            AND grade = 'DOC'
            AND grade_field = doc_id
        UNION
        SELECT grade,
            dep_active,
            1 "priority number"
        FROM
            vrsc.inst_department
        WHERE
            af_feature_id = department_id
            AND grade = 'CUSTOMER'
            AND grade_field IN (
                SELECT
                    doc_cust_id
                FROM
                    customer_docs
                WHERE
                    doc_id = doc_id)
        UNION
        SELECT
            grade,
            dep_active,
            0 "priority number"
        FROM
            vrsc.inst_department
        WHERE
            af_feature_id = department_id
            AND grade = 'DEFAULT'
            AND GRADE_FIELD = 'DEFAULT'
        UNION
        SELECT
            grade, dep_active,
            2 "priority number"
        FROM
            vrsc.groups_docs left
            JOIN vrsc.inst_department ON grade = 'GROUP'
                                      AND grade_field = gs_group_id
                                      AND grade_sec_field = gs_doc_code
        WHERE
            gs_doc_id = doc_id
            AND af_feature_id = feature_id
        ORDER BY
            "priority number" DESC
            )
        WHERE
            ROWNUM = 1 group by dep_active;
            if cnt=0 then
            result:=0;
            end if;
    
        RETURN result;
    END;

我想获取优先级为 3 的第一行,但如果此查询为 null,则我无法将 0 作为 DEFAULT 返回。

【问题讨论】:

  • 如果您使用这些参数运行“SELECT AND UNION INSIDE”子查询,结果是什么样的?如果它返回null, 1,则会导致此问题。
  • 你写的代码看起来有点糟糕(不要误会我的意思,但是...... ROWNUM = 1 的聚合看起来很可疑)。如果您发布一些示例数据并解释某些部门被认为是“活跃的”意味着什么,也许会更好。也许有人会提出比你更好的方法。
  • @kfinity 我把部分放在 select 和 union 里面,它给了我空
  • @Littlefoot 我编辑并把部分放在里面:选择和联合
  • 我发布了一个答案;请看一下。

标签: sql oracle function count


【解决方案1】:

查看NVL 函数,然后试试这个:

  if nvl(cnt,0) = 0 then
    result:=0;
  end if;

【讨论】:

  • 我之前尝试过,但给我返回null而不是0。我认为线索在rownum上,也许是为了推测它的结果。
  • NVL 不可能像那样返回 null。
  • 我知道了。我不知道为什么。
【解决方案2】:

在您编辑问题并包含整个代码之后,我无话可说;我相信您编写的查询实际上决定了部门是否处于活动状态。

我建议使用这样的代码 - 简化 - 来决定最终结果:

with temp as
  (select bunch of things you currently select)
select nvl(max(1), 0)
  into result
  from dual
  where exists (select null from temp);

没有IFs、ROWNUMs、COUNTs……就这么简单(虽然“一堆东西”很复杂)。

或者,放入函数中:

create or replace function 
  is_department_active (department_id in varchar2, doc_id in varchar2)
  return number 
is
  result number(1);
begin
  with temp as(select grade,
                    dep_active,
                    3 "priority number"
             from vrsc.inst_department
             where af_feature_id = department_id
                   and grade = 'doc'
                   and grade_field = doc_id
             union
             select grade,
                    dep_active,
                    1 "priority number"
             from vrsc.inst_department
             where af_feature_id = department_id
                   and grade = 'CUSTOMER'
                   and grade_field in(select doc_cust_id
                                from customer_docs
                                where doc_id = doc_id
                                     )
             union
             select grade,
                    dep_active,
                    0 "priority number"
             from vrsc.inst_department
             where af_feature_id = department_id
                   and grade = 'DEFAULT'
                   and grade_field = 'DEFAULT'
             union
             select grade,
                    dep_active,
                    2 "priority number"
             from vrsc.groups_docs left
             join vrsc.inst_department on grade = 'GROUP'
                                          and grade_field = gs_group_id
                                          and grade_sec_field = gs_doc_code
             where gs_doc_id = doc_id
                   and af_feature_id = feature_id
             order by "priority number" desc)
  select nvl(max(1), 0)
  into result
  from temp
  where exists (select null from temp);

  return result;
end;

看看有没有帮助。

【讨论】:

  • 如果你看图片,我需要第一行。它可能是活动的 = 1 或不活动的 = 0,不管是什么。但是通过我的查询,例如当它为 null 时,它应该假定 value = 0, DEFAULT。
  • @Littlefoot:也许 OutofMemoryError 的要求不同。他不需要计数,而是按优先级排序并取结果是活动的还是不活动的。你可以查看他的代码。没错,只需要检测空结果并与0交换即可。仅此而已。
【解决方案3】:

解决了。

在我原来的函数中,我用 EXCEPTION 替换了 IF 语句并删除了计数器

--previous code  without IF   
RETURN result;
    
      EXCEPTION
        WHEN NO_DATA_FOUND
        THEN
        RETURN 0;
    END;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多