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 在做什么。我看不出您的查询会返回重复值的原因。如有必要,您可以将其放回原处。

我还假设voornamachternaam 来自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如何在没有返回行时显示自定义文本的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL自定义函数

从 0jdbc6 JDBCthin 驱动程序调用具有自定义对象返回类型的 Oracle PL/SQL 过程

违反约束时显示自定义消息 PL/SQL

使用自定义类型参数创建一个过程。 PL/SQL

没有返回行时如何在 Ag Grid 中添加占位符?

自定义 SQL 函数 - PL/SQL:语句被忽略