使用“SELECT INTO”时,Oracle PL / SQL - ORA-01403“未找到数据”

时间:2014-12-02 20:20:57

标签: plsql oracle11g

我有一个pl sql代码,它按顺序执行三个查询以确定匹配级别并执行一些逻辑
问题是 - 当第一个查询没有结果(完全有效的场景)时,我得到ORA-01403没有找到数据。
我明白我需要在NO_DATA_FOUND中加入[Exception子句] - 但是如何添加它并继续下一个查询?

PL/SQL Code
     SELECT A into PARAM A FROM SAMPLE WHERE SOME CONDITION;
     --  GOT ORA-01403  No data found HERE 

     MATCH_LEVEL =1;
     if A is null then 
          do some logic;
     end if


     SELECT A INTO PARAM_B FROM SAMPLE WHERE SOME OTHER CONDITION
     MATCH_LEVEL =2
     if A is null then 
          do some logic 2;
     end if



     SELECT A INTO PARAM_B FROM SAMPLE WHERE SOME OTHER CONDITION
     MATCH_LEVEL =3
     if A is null then 
          do some logic 3;
     end if

END    PL/SQL Code

4 个答案:

答案 0 :(得分:3)

SELECT INTO

围绕begin-end;
begin 

    -- your faulty statement here
Exception
When NO_DATA_FOUND Then
    -- Do what you want or nothing 
WHEN TOO_MANY_ROWS THEN
    -- what if you get more then one row? and need specific handler for this 
When OTHERS Then
    -- do something here or nothing (optional - may happen if you have more than your SELECT INTO between 'begin' and 'Exception')

end;

这就像try

PL/Sql块一样

使用此技术,您可以记录语句失败的原因。

答案 1 :(得分:3)

Declare
--your declarations 
begin
SELECT A into PARAM A FROM SAMPLE WHERE SOME CONDITION;
 --  GOT ORA-01403  No data found HERE 

 Begin

   MATCH_LEVEL =1;
   if A is null then 
        do some logic;
   end if;
 EXCEPTION 
 WHEN NO_DATA_FOUND THEN 
  dbms_output.put_line ('Error...'); 
 END; 
 --- and son on for other blocks

end;

答案 2 :(得分:2)

对于SELECT ... INTO ...语句,PL / SQL引擎假定查询返回一行,且只返回一行。如果没有行或多个行,则会引发异常。

FWIW,您可以通过使用聚合函数来处理此类情况,而无需使用异常处理。这样,总是只是结果集中的一行。

假设您的行中A不能为NULL

 SELECT MAX(A) into PARAM A FROM SAMPLE WHERE SOME CONDITION;
 -- A would be NULL if there was *no* row. Otherwise, it is *the* value for *the* row

 MATCH_LEVEL =1;
 if A is null then 
      do some logic;
 end if

如果NULL值是可能的情况,只需添加额外的COUNT(*)列:

 SELECT MAX(A), COUNT(*) into A, HAS_FOUND_ROW FROM SAMPLE WHERE SOME CONDITION;

 if HAS_FOUND_ROW > 0 then
     ...
 end if;

答案 3 :(得分:1)

Oracle不允许您在不返回任何行的情况下打开隐式游标(即代码块正文中的select语句)。你有两个选择(3个真正的,计算@ Sylvain的答案,但这是一种不寻常的方法):使用显式游标或处理错误。

显式光标

显式游标是DECLARE部分中的游标,必须手动打开并提取(或在FOR循环中)。这有一个额外的好处,如果您正确地参数化查询,您可以编写一次并多次使用它。

DECLARE
   a sample.a%type;
   MATCH_LEVEL number;
   cursor cur_params (some_column_value number) is
     SELECT A FROM SAMPLE WHERE some_column = some_column_value;
BEGIN
   MATCH_LEVEL := 1;
   open cur_params (match_level);
   fetch cur_params into a;
   close cur_params;
   if A is null then 
        null;  --some logic goes here
   end if;

   MATCH_LEVEL := 2;
   open cur_params (match_level);
   fetch cur_params into a;
   close cur_params;
   if A is null then 
        null;  --some logic goes here
   end if;
end;

处理错误

如果您选择处理错误,则需要围绕将引发错误的代码创建BEGIN...END块。当忽略错误时,确保您只是忽略您希望避免的特定错误,从您期望的特定语句生成时,这一点至关重要。例如,如果您只是将EXCEPTION部分添加到现有的BEGIN...END块中,您就无法知道哪个语句生成了它,或者即使它确实是您预期的错误。

DECLARE
   a sample.a%type;
   MATCH_LEVEL number;
BEGIN
   MATCH_LEVEL := 1;
   BEGIN
      SELECT A into A FROM SAMPLE WHERE some_column = MATCH_LEVEL;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         null; --Do nothing
   END;
   if A is null then 
        null;  --some logic goes here
   end if;

   MATCH_LEVEL := 2;
   BEGIN
      SELECT A into A FROM SAMPLE WHERE some_column = MATCH_LEVEL;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         null; --Do nothing
   END;
   if A is null then 
        null;  --some logic goes here
   end if;
end;

虽然我不鼓励它,但您可以在同一个异常块中捕获任何其他错误。但是,根据定义,这些错误是出乎意料的,所以放弃它们是不好的做法(你永远不会知道它们甚至发生了!)。一般来说,如果在异常处理中使用WHEN OTHERS子句,则该子句应始终以RAISE;结束,以便将错误传递到下一级并且不会丢失。