简体   繁体   English

未达到PL / SQL异常,函数不返回

[英]PL/SQL exception not reached, function doesn't return

I have a PL/SQL function and it doesn't seem to reach an exception when I encounter no_data_found. 我有一个PL / SQL函数,当遇到no_data_found时似乎没有出现异常。 I have looked through and tried to add my select statement into its own begin block but I alway get syntax errors. 我浏览了一下,试图将我的select语句添加到它自己的begin块中,但是我总是遇到语法错误。 Where do I need to put the exception ? 我需要在哪里放置例外? Thank you 谢谢

create or replace FUNCTION is_artikl_eligible_for_zamjena (
--input vars
inSifraArtikla IN A_ZAMJENA_ARTIKLI.SIFRA_ARTIKLA%type, 
inDatumPocetak IN VARCHAR2, 
inSkladiste IN A_ZAMJENA.SKL%type,
inProdavaonice IN A_ZAMJENA.POPIS_PROD%type
)
RETURN NUMBER
is 
existingSifraArtikla A_ZAMJENA_ARTIKLI.SIFRA_ARTIKLA%type;
existingBrojZamjene A_ZAMJENA.BROJ_ZAMJENE%type;
existingDatumKraj A_ZAMJENA.DATUM_KRAJ%type;
existingSkladiste A_ZAMJENA.SKL%type;
existingProdavaonice A_ZAMJENA.POPIS_PROD%type;
BEGIN

  dbms_output.enable();
  --check if there is sifra_artikla in a_zamjena_artikli where     a_zamjena.datumKraj != null or a_zamjena.datumKraj > sysdate
  for i IN (
  SELECT azam.BROJ_ZAMJENE, azam.DATUM_KRAJ, azam.SKL, azam.POPIS_PROD, azamAr.SIFRA_ARTIKLA
  FROM A_ZAMJENA azam JOIN A_ZAMJENA_ARTIKLI azamAr 
  ON  azam.BROJ_ZAMJENE = azamAr.BROJ_ZAMJENE
  WHERE azamAr.SIFRA_ARTIKLA = inSifraArtikla
  )

LOOP
existingBrojZamjene :=i.BROJ_ZAMJENE; 
--existingDatumKraj := TO_CHAR(COALESCE(i.DATUM_KRAJ,'21-01-25 00:00'));
existingDatumKraj := i.DATUM_KRAJ;
existingSkladiste := COALESCE(i.SKL, '0');
existingProdavaonice := COALESCE(i.POPIS_PROD, 0);
existingSifraArtikla := i.SIFRA_ARTIKLA;

  if existingDatumKraj IS NOT NULL AND existingDatumKraj < (sysdate -1) then --level 0
      dbms_output.put_line('Datum kraj postojeće zamjene nije null ali je završio');
      return 1;

     else
     if (existingDatumKraj IS NULL) OR (existingDatumKraj > sysdate) then --level 1
      dbms_output.put_line('Zamjene imaju preklapajuće datume, provjeravam da li su na istim skladištima ili prodavaonicama');

         if existingSkladiste != inSkladiste OR existingProdavaonice != inProdavaonice then -- level 2
          dbms_output.put_line('Zamjene imaju preklapajuće datume ali nisu na istim skladištima ili prodavaonicama');
           return 1;

         else -- level 2
         return 0;  
        end if; --level 2
     else --else za datum kraj, level 1
     dbms_output.put_line('Zamjene nemaju preklapajuće datume');
     return 1;

    end if; --level 1
  end if; --level 0
  END LOOP;

EXCEPTION WHEN NO_DATA_FOUND THEN 
dbms_output.put_line('nema retka');

RETURN 1;

END;

Untested, but I would probably use a local variable to check whether my cursor loop found any rows, and check that at the end. 未经测试,但我可能会使用局部变量来检查光标循环是否找到任何行,并在末尾进行检查。 (It could be a Boolean or a counter or something else. I've used a counter below.) (它可以是一个布尔值或一个计数器或其他东西。我在下面使用了一个计数器。)

create or replace function is_artikl_eligible_for_zamjena
    ( insifraartikla in a_zamjena_artikli.sifra_artikla%type
    , indatumpocetak in varchar2
    , inskladiste    in a_zamjena.skl%type
    , inprodavaonice in a_zamjena.popis_prod%type )
    return number
is
    rows_found pls_integer := 0;
begin
    dbms_output.enable();

    -- check if there is sifra_artikla in a_zamjena_artikli where a_zamjena.datumKraj != null or a_zamjena.datumKraj > sysdate
    for i in (
        select azam.broj_zamjene
             , azam.datum_kraj
             , coalesce(azam.skl,'0') as skl
             , coalesce(azam.popis_prod,0) as popis_prod
             , azamar.sifra_artikla
        from   a_zamjena azam
               join   a_zamjena_artikli azamar
               on     azamar.broj_zamjene = azam.broj_zamjene
        where  azamar.sifra_artikla = insifraartikla
    )    
    loop
        rows_found := rows_found +1;

        if i.datum_kraj < sysdate - 1 then
            --level 0
            dbms_output.put_line('Datum kraj postojeće zamjene nije null ali je završio');
            return 1;

        else
            if i.datum_kraj is null or i.datum_kraj > sysdate then
                --level 1
                dbms_output.put_line('Zamjene imaju preklapajuće datume, provjeravam da li su na istim skladištima ili prodavaonicama');

                if i.skl != inskladiste or i.popis_prod != inprodavaonice then
                    -- level 2
                    dbms_output.put_line('Zamjene imaju preklapajuće datume ali nisu na istim skladištima ili prodavaonicama');
                    return 1;

                else
                    -- level 2
                    return 0;
                end if; --level 2
            else
                --else za datum kraj, level 1
                dbms_output.put_line('Zamjene nemaju preklapajuće datume');
                return 1;

            end if; --level 1
        end if; --level 0
    end loop;

    if rows_found = 0 then
        raise no_data_found;
    end;
exception
    when no_data_found then
        dbms_output.put_line('nema retka');

        return 1;

end;

I'm not sure raising a no_data_found exception is a particularly good approach here, though. 我不确定在这里引发no_data_found异常是否是一种特别好的方法。 In fact I'm not keen on a return inside a loop either. 实际上,我也不希望在循环内return Maybe the problem goes away if you just assign the value you want to return to a local variable during the loop, and check it at the end, handling the case where it has no value. 如果仅在循环期间分配要返回给局部变量的值,然后在最后检查它,处理它没有值的情况,则问题可能会消失。

With a local variable and a single return point instead of manipulating exception handlers, it would look something like this: 使用局部变量和单个返回点而不是操纵异常处理程序,它看起来像这样:

create or replace function is_artikl_eligible_for_zamjena
    ( insifraartikla in a_zamjena_artikli.sifra_artikla%type
    , indatumpocetak in varchar2
    , inskladiste    in a_zamjena.skl%type
    , inprodavaonice in a_zamjena.popis_prod%type )
    return number
is
    l_result number;
begin
    dbms_output.enable();

    -- check if there is sifra_artikla in a_zamjena_artikli where a_zamjena.datumKraj != null or a_zamjena.datumKraj > sysdate
    for i in (
        select azam.broj_zamjene
             , azam.datum_kraj
             , coalesce(azam.skl,'0') as skl
             , coalesce(azam.popis_prod,0) as popis_prod
             , azamar.sifra_artikla
        from   a_zamjena azam
               join   a_zamjena_artikli azamar
               on     azam.broj_zamjene = azamar.broj_zamjene
        where  azamar.sifra_artikla = insifraartikla
    )    
    loop
        if i.datum_kraj < sysdate - 1 then
            --level 0
            dbms_output.put_line('Datum kraj postojeće zamjene nije null ali je završio');
            l_result := 1;

        else
            if i.datum_kraj is null or i.datum_kraj > sysdate then
                --level 1
                dbms_output.put_line('Zamjene imaju preklapajuće datume, provjeravam da li su na istim skladištima ili prodavaonicama');

                if i.skl != inskladiste or i.popis_prod != inprodavaonice then
                    -- level 2
                    dbms_output.put_line('Zamjene imaju preklapajuće datume ali nisu na istim skladištima ili prodavaonicama');
                    l_result := 1;

                else
                    -- level 2
                    l_result := 0;
                end if; --level 2
            else
                --else za datum kraj, level 1
                dbms_output.put_line('Zamjene nemaju preklapajuće datume');
                l_result := 1;

            end if; --level 1
        end if; --level 0
    end loop;

    if l_result is then
        dbms_output.put_line('nema retka');
        l_result := 1;
    end;

    return l_result;
end;

I'm not sure what the dbms_output.put_line calls are doing, but that's another question. 我不确定dbms_output.put_line调用在做什么,但这是另一个问题。

You simply cannot raise a NO_DATA_FOUND exception using a for loop. 您根本无法使用for循环引发NO_DATA_FOUND异常。 You can do using a goto statement for insatance. 您可以使用goto语句来避免伤害。 See below example. 请参见以下示例。

DECLARE
   v_attr char(88);
CURSOR  SELECT_USERS IS
 SELECT id 
 FROM USER_TABLE
 WHERE USERTYPE = 'X';
BEGIN
    FOR user_rec IN SELECT_USERS 
     LOOP    
        BEGIN
            SELECT attr 
            INTO v_attr 
            FROM ATTRIBUTE_TABLE
            WHERE user_id = user_rec.id;            
         EXCEPTION
            WHEN NO_DATA_FOUND THEN
               -- user does not have attribute, continue loop to next record.
               goto end_loop; ---Adding a label
         END;

        <<end_loop>> --Label
        null;         
    END LOOP;
END;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM