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

PL/SQL How to display a custom text when no row is returned

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

如果他们没有任何专业化,则需要 return "no specialisations found"。

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

这是我的代码(在 sqldeveloper 中)

CREATE OR REPLACE PROCEDURE OVERZICHT_SPECIALISATIES AS 

此游标包含所有员工

cursor cur_per is
select voornaam, achternaam
from personeel;

此游标包含员工的专业化,但如果他们有 none 它只是 return 没有找到行,这是我想测试的

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;    

提前致谢。

您可以使用 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 table。

您可以使用为每个人设置为 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 包含在第一个子句的 select 列表中,并且只将其作为游标参数传递;那么第二个游标就不需要再次查询 personeel table:

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