在PL/SQL函数中,如何在select语句中使用多个大小写?

在PL/SQL函数中,如何在select语句中使用多个大小写?,sql,oracle,plsql,Sql,Oracle,Plsql,我正在尝试编写一个包含两个case语句的函数。在后台,用户可以有a、B或同时有a和B(但在单独的行上,这就是为什么我不能使用单个case语句,除非我使用listag,我被告知不要这样做) 样本数据: User State 1 A 1 B 2 A 3 B SQL 对于想要的结果,当我输入用户1时,我希望返回AB,对于用户2=A和用户3=B。我也尝试了使用两个不同的select语句块,但也无法使其工作,因为某种原因,它只会命中异常处理程序。谢

我正在尝试编写一个包含两个case语句的函数。在后台,用户可以有a、B或同时有a和B(但在单独的行上,这就是为什么我不能使用单个case语句,除非我使用listag,我被告知不要这样做)

样本数据:

User State 
1       A 
1       B 
2       A 
3       B
SQL


对于想要的结果,当我输入用户1时,我希望返回AB,对于用户2=A和用户3=B。我也尝试了使用两个不同的select语句块,但也无法使其工作,因为某种原因,它只会命中异常处理程序。谢谢!

使用下面的代码,现在您将只得到一行结果

SELECT MAX(CASE WHEN state = 'A' THEN 'A'
                ELSE null END),    
       MAX(CASE WHEN state = 'B' THEN 'B'
                ELSE null END)
INTO l_A, l_B
FROM TABLE1
 WHERE state in ('A', 'B')
   AND TABLE1_CODE = code
   AND TABLE1_ID   = id
   AND TABLE1_TIME = time;

一个非常简单的方法可能是: 不清楚是否要检查记录是否存在,因为在异常块中返回“NO DATA”,而在case语句中返回值“note”。无论如何,您可以相应地调整此值:

CREATE OR REPLACE Function F_Calc_State( code varchar2
                                       , id number
                                       , time varchar2
                                       ) return varchar2 
as
  l_count_a number;
  l_count_b number;
  l_result varchar2(10);

begin

  select count(*)
    into l_count_a
    from table1
   where state = 'A'
     and table1_code = id
     and table1_time = time;

  select count(*)
    into l_count_b
    from table1
   where state = 'B'
     and table1_code = id
     and table1_time = time;

  if    l_count_a = 0 and l_count_b = 0 then l_result := 'NEITHER'; 
  elsif l_count_a > 0 and l_count_b = 0 then l_result := 'A';
  elsif l_count_a = 0 and l_count_b > 0 then l_result := 'B';
  elsif l_count_a > 0 and l_count_b > 0 then l_result := 'AB';
  else  l_result := '';
  end if;

  return l_result;
end F_Calc_State;

如果未找到数据,以下代码将返回
NULL

CREATE OR REPLACE Function F_Calc_State (
    in_code Varchar2,
    in_id Number,
    in_time varchar2  -- "time" as a string is highly suspicious
) Return Varchar2 
AS
    v_ab varchar2(10) := null;
BEGIN

    SELECT MAX(CASE WHEN t1.state = 'A' THEN 'A' END) ||
           MAX(CASE WHEN t1.state = 'B' THEN 'B' END)
    INTO v_AB
    FROM  TABLE1 t1
    WHERE t1.state in ('A', 'B') AND
          t1.TABLE1_CODE = in_code AND
          t1.TABLE1_ID = in_id AND
          t1.TABLE1_TIME = in_time;    
    RETURN(v_ab);
END;  -- F_Calc_State
但是,如果找不到数据,则不会返回错误

CREATE OR REPLACE Function F_Calc_State (
    in_code Varchar2,
    in_id Number,
    in_time varchar2  -- "time" as a string is highly suspicious
) Return Varchar2 
AS
    v_ab varchar2(10) := null;
BEGIN

    SELECT MAX(CASE WHEN t1.state = 'A' THEN 'A' END) ||
           MAX(CASE WHEN t1.state = 'B' THEN 'B' END)
    INTO v_AB
    FROM  TABLE1 t1
    WHERE t1.state in ('A', 'B') AND
          t1.TABLE1_CODE = in_code AND
          t1.TABLE1_ID = in_id AND
          t1.TABLE1_TIME = in_time;  
    GROUP BY t1.TABLE1_CODE;  -- this will return no rows if there are no matches

    RETURN(v_ab);

    EXCEPTION
        WHEN NO_DATA_FOUND THEN RETURN 'NO DATA';
        WHEN OTHERS THEN RETURN SQLERRM ;

END;  -- F_Calc_State

在select中只能有一个
into
语句。而且我认为OP应该在
Calc_State:=nvl(l_a | l|u B,'note'之后使用;
@kfinity…double
into
语句取自OP的代码。这是错误的,应该已经修复,但注释可能更好地指向OP。因此,为了澄清,我不能在一个select语句中包含double-into语句?我不能使用GauraS的解决方案。您了解“循环”是如何工作的吗(在一般的计算中,不一定在PL/SQL中)?在您的代码中,您在基表中的行上循环-在具有指定id和时间值的行上循环,并在“A”、“B”中进行状态。这些行一次读取和处理一行,不同迭代之间没有连接。在id=1的情况下,首先读取其中一行(除非您添加ORDER BY,否则您不知道-您不知道-先读取哪一行,但这不会有任何帮助)。一个变量设置为“A”(或“B”,取决于先读取哪一行)然后读取光标中的下一行,覆盖所有变量,
calc\u state
使用变量的最后一个值计算。无“内存”当变量被再次分配给第二行时,第一行发生了什么。函数将返回循环最后一次迭代后的值。这就是为什么你永远不会以这种方式得到期望的结果。更好的问题是,你为什么要尝试在PL/SQL中这样做?一个微不足道的问题(而且要快很多倍)解决方案是在一个简单的SQL语句中完成这一切。即使您需要编写函数,也可以简单地选择状态(a和/或B)的串联或者这仅仅是练习PL/SQL编码的一个练习?我从概念的角度熟悉循环,因此我很感谢您在具体示例中解释它是如何工作的。不过,在这个示例中,我传递了一个唯一的ID以及表约束(state in('a','B'))因此,我假设这对ID=1有效,因为它在一个“循环”中填充了2个变量。虽然从其他方面来看,我似乎不能使用2“into”语句。至于原因,最终用户将能够使用自己来确定他们的用户处于什么状态。另外,谢谢!这是
选择x,y intox1,y1来自任何一个
。这很有效。我写了几乎相同的东西,但使用了case语句(在两个单独的select块中,以及底部类似于“if…then”语句的大小写中。但是,我无法让它工作。当用户为a或B时,它将跳转到异常处理程序。我假设,因为它没有使用两个select语句中的一个。但这似乎没有遇到该问题。谢谢!在PLSQL中运行SQLs时遇到的典型异常是找不到数据,行太多。这两个异常都不会以我创建SQLs的方式出现:我使用count()作为聚合函数。这样,就不会找到无数据(但只会将0作为值)你也不必担心太多的行。因此,我这里根本没有异常处理程序。我感谢你的评论,尤其是可疑的“time”作为varchar。我实际上将其重命名为“time period”,其中包含字母……说来话长。关于你的代码,它是有效的,我决不会将2个case statem串联起来另外,我不知道max()在这方面有什么作用。你能简单解释一下吗?谢谢
CREATE OR REPLACE Function F_Calc_State (
    in_code Varchar2,
    in_id Number,
    in_time varchar2  -- "time" as a string is highly suspicious
) Return Varchar2 
AS
    v_ab varchar2(10) := null;
BEGIN

    SELECT MAX(CASE WHEN t1.state = 'A' THEN 'A' END) ||
           MAX(CASE WHEN t1.state = 'B' THEN 'B' END)
    INTO v_AB
    FROM  TABLE1 t1
    WHERE t1.state in ('A', 'B') AND
          t1.TABLE1_CODE = in_code AND
          t1.TABLE1_ID = in_id AND
          t1.TABLE1_TIME = in_time;  
    GROUP BY t1.TABLE1_CODE;  -- this will return no rows if there are no matches

    RETURN(v_ab);

    EXCEPTION
        WHEN NO_DATA_FOUND THEN RETURN 'NO DATA';
        WHEN OTHERS THEN RETURN SQLERRM ;

END;  -- F_Calc_State