PL/SQL如何在没有返回行时显示自定义文本
Posted
技术标签:
【中文标题】PL/SQL如何在没有返回行时显示自定义文本【英文标题】:PL/SQL How to display a custom text when no row is returned 【发布时间】:2015-01-11 17:53:13 【问题描述】:我有这个任务,我必须通过一个名为“personeel”、“pers”或“per”的所有员工的程序来了解专业领域的概况。(荷兰语表格和属性)
如果他们没有任何专业化,那么它需要返回“未找到专业化”。
问题是当我使用游标(这是我们需要解决这个问题的方式)并且我使用 for 循环时,我似乎无法测试这个人是否没有专长。我也真的不知道如何在互联网上搜索。我似乎发现的只是光标属性,但这不起作用。
这是我的代码(在 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;
提前致谢。
【问题讨论】:
【参考方案1】:您可以使用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
表。
【讨论】:
group by 仍然是较早的计数测试的剩余部分。感谢您的关注 :) 通常我会进行内部连接,但我们不得不从几个月前重写这段代码,当时我还没有这样做。 我用内部连接测试了它,它似乎不再起作用了。为什么这不可能? @kevin 。 . .因为内连接会过滤掉不匹配的行。【参考方案2】:您可以使用为每个人设置为 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
包含在第一个子句的选择列表中,并且只将其作为游标参数传入;那么第二个游标就不需要再次查询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
【讨论】:
感谢输入,不知道没有找到记录时他没有进入循环。 group by 仍然是较早的计数测试的剩余部分。感谢您的关注:)这也有效,谢谢! @Kevin - 对于外连接版本,您仍然需要再次访问personeel
表;即使你真的想这样做,我仍然会传递 persnr
而不是名字,所以你知道你正在寻找一个人 - 以防有重复的名字。
嗯,作业要我们搜索名字。我知道这确实不是最好的方法。但如果这是老师要我们做的……他已经做到了,所以没有重复的名字。
@Kevin - 很公平。奇怪,但有时无法与要求争论。以上是关于PL/SQL如何在没有返回行时显示自定义文本的主要内容,如果未能解决你的问题,请参考以下文章