Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Plsql pl/sql块进入无限循环_Plsql - Fatal编程技术网

Plsql pl/sql块进入无限循环

Plsql pl/sql块进入无限循环,plsql,Plsql,ES表有日期和金额,我想将金额作为ES中给定日期的最新可用日期的o/p 例如: 如果“20160223”中的日期和ES中的金额可用于“20160220”,则该金额应在v_中返回,同时循环应退出。但这是无限的。请建议所需代码中的更正。更改: create or replace function f_amt(date_in in varchar2) return number as BEGIN DECLARE v_at ES.AMT%TYPE; i

ES表有日期和金额,我想将金额作为ES中给定日期的最新可用日期的o/p

例如: 如果“20160223”中的日期和ES中的金额可用于“20160220”,则该金额应在v_中返回,同时循环应退出。但这是无限的。请建议所需代码中的更正。

更改:

create or replace
function f_amt(date_in in varchar2) return number 
as 
BEGIN 
DECLARE 
   v_at            ES.AMT%TYPE; 
   i                number := 0;
   BEGIN 

      v_at := 0;
      WHILE v_at = 0 
      LOOP
        BEGIN
        select nvl(AMT,0) 
        into v_at 
        from es 
        where date1 = to_date(date_in,'MM/DD/YYYY') - i; 
        i := i + 1;    
        EXCEPTION when NO_DATA_FOUND 
        then
        v_at:=0; 
      END;
      END LOOP;
      RETURN v_at; 
   END; 
EXCEPTION 
  WHEN OTHERS THEN 
     RETURN 0;
END;
与:

无限循环发生,因为在某些i中,始终没有找到异常的数据,而v_at始终为0。你可以写

EXCEPTION when NO_DATA_FOUND 
        then
        exit; 
当其他人出现异常时,尽量不要使用异常。当其他事情发生时,你想看到它。如果经常调用某个函数,请尽量避免异常。他们必须是真正的例外。它们很贵。当您希望找不到数据时,请不要选择“进入打开的光标”并使用%NOTFOUND或“用于循环”。

更改:

create or replace
function f_amt(date_in in varchar2) return number 
as 
BEGIN 
DECLARE 
   v_at            ES.AMT%TYPE; 
   i                number := 0;
   BEGIN 

      v_at := 0;
      WHILE v_at = 0 
      LOOP
        BEGIN
        select nvl(AMT,0) 
        into v_at 
        from es 
        where date1 = to_date(date_in,'MM/DD/YYYY') - i; 
        i := i + 1;    
        EXCEPTION when NO_DATA_FOUND 
        then
        v_at:=0; 
      END;
      END LOOP;
      RETURN v_at; 
   END; 
EXCEPTION 
  WHEN OTHERS THEN 
     RETURN 0;
END;
与:

无限循环发生,因为在某些i中,始终没有找到异常的数据,而v_at始终为0。你可以写

EXCEPTION when NO_DATA_FOUND 
        then
        exit; 

当其他人出现异常时,尽量不要使用异常。当其他事情发生时,你想看到它。如果经常调用某个函数,请尽量避免异常。他们必须是真正的例外。它们很贵。当您希望找不到数据时,请不要选择“进入打开的光标”并使用%NOTFOUND或“用于循环”。

如果没有先前的值,会发生什么

这样做不是更简单、更快、更安全吗:

CREATE OR REPLACE FUNCTION f_amt (date_in IN VARCHAR2)
   RETURN NUMBER
AS
BEGIN
   FOR c1 IN (  SELECT amt
                  FROM es
                 WHERE date1 <= TO_DATE (date_in, 'MM/DD/YYYY')
                   AND nvl(amt,0) <> 0
              ORDER BY date1 DESC)
   LOOP
      RETURN c1.amt;
   END LOOP;

   RETURN 0;
END;
没有循环,只要date1上有索引,就只有两个索引查找。
另外,您没有提到date1是否唯一,但如果不是,您的代码也会失败。

如果没有先前的值,会发生什么

这样做不是更简单、更快、更安全吗:

CREATE OR REPLACE FUNCTION f_amt (date_in IN VARCHAR2)
   RETURN NUMBER
AS
BEGIN
   FOR c1 IN (  SELECT amt
                  FROM es
                 WHERE date1 <= TO_DATE (date_in, 'MM/DD/YYYY')
                   AND nvl(amt,0) <> 0
              ORDER BY date1 DESC)
   LOOP
      RETURN c1.amt;
   END LOOP;

   RETURN 0;
END;
没有循环,只要date1上有索引,就只有两个索引查找。
另外,您没有提到date1是否唯一,但如果不是,您的代码也会失败。

如果没有date1如果没有date1,最好不要在其他情况下使用,因为我们也会在date1重命名为date2时吞下异常,因此永远不知道函数为什么总是突然返回0。然而,当这里显然使用了OTHERS来捕获所有可能的截止日期异常时。因此,只要函数任务的一部分是在无效的日期字符串上返回0,就需要像广泛异常处理这样的操作。这里有一个线程正好处理这个问题:@ThorstenKettner我明白了,但我不认为,如果你给这个函数传递一个日期'20160223',并且你期望一个'MM/DD/YYYY'格式,那么接受这个例外是个好主意,你是对的;应通知调用方给定的日期字符串被视为无效。那会好得多。它归结为:该函数验证日期字符串,并在有效的情况下获取金额。这应该是两个独立的任务。接口设计很糟糕。该函数当前转换一个不明确的日期字符串,您只需知道该字符串并为结果日期返回一个值,因此它做了两件事,其中一件是隐式的。为了正确地完成验证工作,它应该彻底检查日期字符串,可能是一个正则表达式和一些显式命名的异常,尽管即使这样,当您指的是2016年2月1日时,您也可以通过2016年1月1日,但它无法判断。最好是要求一个实际的日期。我认为字符串更容易让OP在前端编写代码。这是一个很好的建议,不要在其他情况下使用,因为当date1重命名为date2时,我们也会接受异常,因此永远不知道函数为什么总是突然返回0。然而,当这里显然使用了OTHERS来捕获所有可能的截止日期异常时。因此,只要函数任务的一部分是在无效的日期字符串上返回0,就需要像广泛异常处理这样的操作。这里有一个线程正好处理这个问题:@ThorstenKettner我明白了,但我不认为,如果你给这个函数传递一个日期'20160223',并且你期望一个'MM/DD/YYYY'格式,那么接受这个例外是个好主意,你是对的;应通知调用方给定的日期字符串被视为无效。那会好得多。它归结为:该函数验证日期字符串,并在有效的情况下获取金额。这应该是两个独立的任务。接口设计很糟糕。该函数当前转换一个不明确的日期字符串,您只需知道该字符串并为结果日期返回一个值,因此它做了两件事,其中一件是隐式的。为了正确地完成验证工作,它应该彻底检查日期字符串,可能是一个正则表达式和一些显式命名的异常,尽管即使这样,当您指的是2016年2月1日时,您也可以通过2016年1月1日,但它无法判断。最好是要求一个实际的日期。我希望字符串更容易让OP在前端编码。顶部有一个额外的begin declare,这无疑是从OP复制的。是的,谢谢William,我在复制代码时没有发现这个。我现在已经更正了,有一个extr
顶部的begin声明无疑是从OP复制的。是的,谢谢William,我在复制代码时没有发现这个。我现在已经纠正了这个问题。