[英]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.