我有一个PL / SQL函数,遇到no_data_found时它似乎没有达到异常。我已经查看并试图将我的select语句添加到它自己的开始块中,但我总是得到语法错误。我需要在哪里放置例外?谢谢
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;
答案 0 :(得分:2)
未经测试,但我可能会使用局部变量来检查我的游标循环是否找到了任何行,并在最后检查。 (它可能是布尔值或计数器或其他东西。我在下面使用了一个计数器。)
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;
我不确定提出no_data_found
例外是一种特别好的做法。事实上,我也不热衷于循环中的return
。如果您只是在循环期间分配要返回局部变量的值,并且最后检查它,处理它没有值的情况,那么问题就会消失。
使用局部变量和单个返回点而不是操作异常处理程序,它看起来像这样:
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;
我不确定dbms_output.put_line
来电正在做什么,但这是另一个问题。
答案 1 :(得分:1)
您无法使用for循环引发NO_DATA_FOUND异常。您可以使用goto语句进行insatance。见下面的例子。
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;