在WHEN条件下不同select语句的Oracle pl/sql case语句

nkhmeac6  于 2023-10-16  发布在  Oracle
关注(0)|答案(2)|浏览(130)

我在pl/sql中有一个CASE语句不起作用,正在寻求帮助。我不是一个Oracle的人,一个SQL的人,所以不太明白为什么这不工作。在SQL中,类似于下面的东西会很好地工作,但显然在Oracle中我缺少了一些东西。
需要说明的是,我尝试根据WHEN条件执行不同的select语句。我已经在IF块中使用EXECUTE IMMEDIATE尝试过了,但也不确定这是否正确。
这是我不断得到的错误:
ORA-00937:不是单组组函数00937。00000 -“不是单组组函数”* 原因:

  • 操作:错误行:186柱:42
SELECT 
    CASE
        WHEN (COUNT(*) > 0) THEN (SELECT id from MyTable)
        WHEN (COUNT(*) = 0) THEN (SELECT id from MyTable2)
    END
FROM TableA TA
        JOIN TableB TB ON TA.id = TB.id
        JOIN TableC TC ON TB.id = TC.id
        WHERE TA.id=1234;
eimct9ow

eimct9ow1#

这不是关于Oracle的编程语言PL/SQL,而是关于Oracle的SQL实现。你是对的,你的查询应该是有效的。聚合应该返回一个计数,根据计数,查询将返回MyTable的ID或MyTable 2的ID或NULL。(当然,如果MyTable或MyTable 2中有多个行,它应该在运行时崩溃。
甲骨文显然在这里有一个bug。解决方法是分两步执行此操作:对行进行计数,然后使用此结果并决定显示哪个ID。

SELECT 
  CASE
    WHEN cnt > 0 THEN (SELECT id FROM mytable)
    WHEN cnt = 0 THEN (SELECT id FROM mytable2)
  END
FROM
(
  SELECT count(*) AS cnt
  FROM tablea ta
  JOIN tableb tb ON ta.id = tb.id
  JOIN tablec tc ON tb.id = tc.id
  WHERE TA.id = 1234
) counted;

演示:https://dbfiddle.uk/FGdQyVpu

8ljdwjyq

8ljdwjyq2#

这在PL/SQL中不起作用。通常,我们计算返回的行数并将其存储到局部变量(在我的示例中为l_cnt)中,然后根据结果使用一个select或另一个:

declare
  l_cnt number;
begin
  select count(*)
    into l_cnt
    from tablea ta join tableb tb on ta.id = tb.id
                   join tablec tc on tb.id = tc.id
    where ta.id = 1234;
    
  if l_cnt > 0 then
     select max(id)
       into l_id
       from mytable;
  elsif l_cnt = 0 then
     select max(id)
       into l_id
       from mytable2;
  end if;
end;

它可能会有一些变化,这取决于你想对你选择的id做什么。注意-如果mytablemytable2中的行数不等于1,您将得到一个错误(no_data_found或too_many_rows;这就是为什么我包含max函数-以避免此类错误)。
你能做什么?例如,将ID值存储到集合中。或者使用游标(for循环)。或者谁知道呢就像我说的,这取决于你想得到什么样的结果。
这里的例子说明了你可能会做什么。
示例表是Scott的emp(员工):

SQL> select deptno, count(*) from emp group by deptno;

    DEPTNO   COUNT(*)
---------- ----------
        20          5
        30          6
        10          3

首先,count将返回 something(当deptno = 10时)并将值取入collection:

SQL> declare
  2    l_deptno    emp.deptno%type := 10;
  3    l_deptno_2  emp.deptno%type := 20;
  4    l_cnt number;
  5    l_col sys.odcinumberlist;
  6    --
  7    l_rc  sys_refcursor;
  8    l_id  emp.empno%type;
  9  begin
 10    select count(*)
 11      into l_cnt
 12      from emp
 13      where deptno = l_deptno;
 14
 15    if l_cnt > 0 then
 16       select empno
 17         bulk collect
 18         into l_col
 19         from emp
 20         where deptno = l_deptno;
 21
 22       for i in 1 .. l_col.count loop
 23         dbms_output.put_line('CNT > 0: ID = ' || l_col(i));
 24       end loop;
 25    elsif l_cnt = 0 then
 26       open l_rc for
 27       select empno
 28         from emp
 29         where deptno = l_deptno_2;
 30
 31       loop
 32         fetch l_rc into l_id;
 33         exit when l_rc%notfound;
 34         dbms_output.put_Line('CNT = 0; ID = ' || l_id);
 35       end loop;
 36    end if;
 37  end;
 38  /
CNT > 0: ID = 7782
CNT > 0: ID = 7839
CNT > 0: ID = 7934

PL/SQL procedure successfully completed.

SQL>

下一个示例将使用refcursor(我将修改第2行中的部门编号,这在第13行中使用):

SQL> l2
  2*   l_deptno    emp.deptno%type := 10;
SQL> c/10/99
  2*   l_deptno    emp.deptno%type := 99;
SQL> /
CNT = 0; ID = 7369
CNT = 0; ID = 7566
CNT = 0; ID = 7788
CNT = 0; ID = 7876
CNT = 0; ID = 7902

PL/SQL procedure successfully completed.

SQL>

相关问题