PL / SQL如何在没有返回行时显示自定义文本

时间:2015-01-11 17:53:14

标签: sql stored-procedures plsql oracle-sqldeveloper procedure

我有这个任务,我必须从所有员工的程序中获得一个名为“personeel”,“pers”或“per”的专业化概述。(荷兰表和属性)

如果他们没有任何专业化,那么它需要返回“没有找到专业化”。

问题是当我使用游标(这是我们需要解决这个问题的方式)并且我使用for循环时,我似乎无法测试该人是否没有专业化。我也不知道如何在互联网上搜索这个。我似乎找到的只是光标attriubutes,但这不起作用。

这是我的代码(在sqldeveloper中)

CREATE OR REPLACE PROCEDURE OVERZICHT_SPECIALISATIES AS 

此光标包含所有员工

cursor cur_per is
select voornaam, achternaam
from personeel;

此游标包含员工的专业化,但如果他们没有,则只返回找不到的行,这是我想要测试的

cursor cur_spec (p_vn PERSONEEL.VOORNAAM%type, p_an PERSONEEL.ACHTERNAAM%type) is
select p.code, s.titel, p.datum_behaald
from pers_specialisaties p, personeel per, specialisaties s
where per.persnr = p.persnr
and p.code = s.code
and voornaam = p_vn
and achternaam = p_an
group by p.code,s.titel, p.datum_behaald;

BEGIN
for r_per in cur_per
loop
dbms_output.put_line(r_per.voornaam || ' ' || r_per.achternaam);
dbms_output.put_line('---------------------------');

for r_spec in cur_spec (r_per.voornaam, r_per.achternaam)
loop

这是我测试的IF语句,但它似乎不起作用

  IF (cur_spec%NOTFOUND)
  THEN
  dbms_output.put_line('no specialisations found');
  ELSE
  dbms_output.put_line(r_spec.code || '    ' || r_spec.titel || ' ' 
                        || r_spec.datum_behaald);
  END IF;
end loop;
dbms_output.put_line(' ');
end loop;

END OVERZICHT_SPECIALISATIES;    

提前感谢。

2 个答案:

答案 0 :(得分:4)

您可以使用left join执行此操作。通常,您应该使用显式join语法 - 它比逗号更强大。实际上,遵循一个简单的规则:永远不要在from子句中使用逗号。

select p.code, coalesce(s.titel, 'no specialisations found') as titel, p.datum_behaald
from personeel per left join
     pers_specialisaties p
     on per.persnr = p.persnr left join
     specialisaties s
     on p.code = s.code
where per.voornaam = p_vn and per.achternaam = p_an;

这会保留personneel中的所有行。如果没有匹配的s.titel,则会获得您想要的字符串。

我不确定group by正在做什么。我没有看到您的查询将返回重复值的原因。如有必要,你可以把它放回去。

我还假设voornamachternaam来自per表。

答案 1 :(得分:1)

您可以使用为每个人设置为false的标志,然后在专业循环内设置为true - 表示至少找到了一个专业。然后测试那个人是真是假;如果它是假的那么你没有进入循环,所以没有专业:

declare
   found_record_flag boolean;
   ...
begin
  for r_per in cur_per
  loop
    dbms_output.put_line(r_per.voornaam || ' ' || r_per.achternaam);
    dbms_output.put_line('---------------------------');

    found_record_flag := false;
    for r_spec in cur_spec (r_per.voornaam, r_per.achternaam)
    loop
      found_record_flag := true;
      dbms_output.put_line(r_spec.code || '    ' || r_spec.titel || ' ' 
                            || r_spec.datum_behaald);
    end loop;

    if found_record_flag = false then
      dbms_output.put_line('no specialisations found');
    end if;

    dbms_output.put_line(' ');
  end loop;
...

你的第二个光标实际上是假设没有两个人拥有相同的名字和姓氏组合。最好在第一个子句的选择列表中包含persnr,并且只将其作为cursor参数传入;然后第二个游标不需要再次查询personeel表:

cursor cur_per is
select persnr, voornaam, achternaam
from personeel;

cursor cur_spec (p_persnr personeel.persnr%type) is
select ps.code, s.titel, ps.datum_behaald
from pers_specialisaties ps
join specialisaties s
on s.code = ps.code
where ps.persnr = p_persnr;

我也不确定为什么要对值进行分组,除非由于名称重复而导致重复。它没有必要。然后是:

    for r_spec in cur_spec (r_per.persnr)
    loop