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
在做什么。我看不出您的查询会返回重复值的原因。如有必要,您可以将其放回原处。
我还假设 voornam
和 achternaam
来自 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
我有这个任务,我必须从所有员工的程序中获得专业化的概述,称为 "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
在做什么。我看不出您的查询会返回重复值的原因。如有必要,您可以将其放回原处。
我还假设 voornam
和 achternaam
来自 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