为什么在此过程中我的条件都没有得到满足?

时间:2018-08-06 19:49:10

标签: oracle plsql

因此,我有一个存储过程(下面出于演示目的已对其进行了简化),该存储过程没有通过任何条件,因此也没有在表中插入/传递任何值。我试过将Java传递的varchar / string转换为数字,但是没有任何效果。下面是我的“简化代码”

Create or Replace Procedure SAMPLE(rValue IN VARCHAR)
IS
v_Max value.value%type;
v_forecast value.value%type;
BEGIN
--
SELECT BUFFER_MAX_VALUE
 INTO v_MAX
 FROM look_up;
--
EXCEPTION 
WHEN no_data_found
THEN SELECT 0
    INTO v_forecast
    FROM DUAL;
--
 IF to_Number(rValue) < 0 OR to_Number(rValue) > v_MAX) 
 THEN 
 dbms_output.put_line('IF1 Works');
 insert into value(value_id, value)
           values(1, rValue);
ELSIF rValue is null OR to_Number(rValue) = 0
 THEN
dbms_output.put_line('IF1A ONLY Works');
 END IF;
ELSE
insert into value(value_id, value)
           values(1, v_forecast);
dbms_output.put_line('IF1 ELSE ONLY Works');
END SAMPLE;

我尝试传递以下内容:

BEGIN
SAMPLE('-7');
END;

2 个答案:

答案 0 :(得分:1)

据我所知,您想让异常部分捕获查找表中什么都没有的情况。在这种情况下,请设置v_forecast,然后继续。这意味着您需要将select放入其自己的块中。

我还通过设置一个常量来避免多次to_number调用。

我摆脱了双重选择中不必要的选择。

我也非常希望您没有一个名为VALUE的表,该表的一个名为VALUE的列。选择更有意义的名称。

看看它如何为您工作。

CREATE OR REPLACE PROCEDURE sample (rvalue IN VARCHAR2)
IS
   c_rvalue   CONSTANT NUMBER := rvalue;
   v_max               VALUE.VALUE%TYPE;
   v_forecast          VALUE.VALUE%TYPE;
BEGIN
   BEGIN
      SELECT buffer_max_value INTO v_max FROM look_up;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         v_forecast := 0;
   END;

   IF c_rvalue < 0 OR c_rvalue > v_max
   THEN
      DBMS_OUTPUT.put_line ('IF1 Works');

      INSERT INTO VALUE (value_id, VALUE)
           VALUES (1, rvalue);
   ELSIF c_rvalue IS NULL OR c_rvalue = 0
   THEN
      DBMS_OUTPUT.put_line ('IF1A ONLY Works');
   ELSE
      INSERT INTO VALUE (value_id, VALUE)
           VALUES (1, v_forecast);

      DBMS_OUTPUT.put_line ('IF1 ELSE ONLY Works');
   END IF;
END sample;

答案 1 :(得分:1)

如果第一个SELECT BUFFER_MAX_VALUE返回任何内容,则不会执行任何其他操作,因为您将一切绝对放入了EXCEPTION部分。如果只打算处理该语句,则应将其包含在其自己的BEGIN-END块中,例如

create procedure ...
begin
  -- its own begin starts now
  begin
    select buffer_max_value into v_max
    from look_up;
  exception
    when no_data_found then 
      -- do something here
  end;
  -- its own end ends now

  -- put the rest of your code here
end;

顺便说一句,LOOK_UP表是否总是不包含行或仅包含一行?因为,正如您所写的SELECT不包含WHERE子句,它可能会引发TOO_MANY_ROWS(您也应该处理)。

您将rValue声明为VARCHAR2,然后对其应用TO_NUMBER。为什么不声明它为NUMBER?因为,没有什么阻止您将'XYZ'传递给该过程,然后TO_NUMBER会因INVALID NUMBER错误而失败。

[编辑:更多异常处理]

EXCEPTION部分处理该BEGIN-END块中发生的所有异常,无论您有多少SELECT条语句。但是,除非您包括一些额外的(简单的)编程,否则您不会知道哪个失败。

请注意,这只是为了显示我的意思;不要使用DBMS_OUTPUT处理错误(很可能没有人会看到它),很少有您想使用WHEN OTHERS处理错误。

create procedure ...
  l_position number;
begin
  l_position := 1;
  select ... into ... from ...;

  l_position := 2;
  select ... into ... 

exception
  when others then
    dbms_output.put_line('Error on position ' || l_position ||' '|| sqlerrm);
    raise;
end;