有没有办法检查游标是不是返回没有记录?

Posted

技术标签:

【中文标题】有没有办法检查游标是不是返回没有记录?【英文标题】:Is there any way to check if cursor return no record?有没有办法检查游标是否返回没有记录? 【发布时间】:2021-05-03 20:59:32 【问题描述】:

我在 PL/SQL 中编写了简单的程序来降低价格。当我调用过程时,我故意传递不在数据库中的参数,因此游标不返回任何数据。 这是问题:我的异常不起作用。 kursor%notfound 之类的表达式检查 kursor 是否不返回任何数据或未声明? 我很困惑,因为在我进行研究时,有人说kursor%notfound 在没有找到数据时返回 true,但在我的程序中它不起作用。说到这里:

 if (kursor%notfound) then
        raise no_data_found;
    end if;

它不会引发异常。我究竟做错了什么? PS 抱歉,语言不一致(混合波兰语和英语),但我有波兰语数据库。

我的整个程序:

  set serveroutput on
create or replace procedure reduce_price(surname_p varchar2,
name_p varchar2, percents number default 5)is

cursor kursor is
    select n.id_mech,cena  from naprawa n
    join mechanik m on m.id_mech = n.id_mech
    where m.imie = name_p and m.nazwisko = surname_p
    for update;
nc number;
begin
    for k in kursor
    loop
       if (kursor%notfound) then
            raise NO_DATA_FOUND;
        end if;
    begin
        
        nc := k.cena *(1-percents/100);
        dbms_output.put_line(k.cena ||' ' ||nc);
        update naprawa set cena =nc
        where id_mech = k.id_mech;
    
        exception
        when NO_DATA_FOUND then
            dbms_output.put_line('no rows found');
    end;
    end loop;    
    
end;

/
begin
  reduce_price('aaa', 'XYZ',1);
end;

感谢您的宝贵时间。

【问题讨论】:

@OldProgrammer 的回答解释了为什么它永远不会引发 NO_DATA_FOUND,但原始代码中的另一个问题是在 RAISE 语句的范围内没有异常处理程序。 【参考方案1】:

那是行不通的。在您的 cursor for 循环中,如果您的代码进入循环,那么这意味着找到一个或多个记录,并且 %notfound 游标属性永远不会为真。你有几个选择。

    在循环中保留一个计数器并在退出后检查

    创建或替换过程 reduce_price(surname_p varchar2, name_p varchar2,百分比数字默认5)是

     nc number;
     cnt number := 0;
     begin
         for k in kursor
         loop
    
             nc := k.cena *(1-percents/100);
             dbms_output.put_line(k.cena ||' ' ||nc);
             update naprawa set cena =nc
             where id_mech = k.id_mech;
             cnt := cnt + 1;
         end loop; 
    
         if cnt = 0 then   
            raise NO_DATA_FOUND;
         end if;
     .. etc..
    

    在进入循环之前检查现有数据

    select count(*)
    into cnt
    from naprawa n
        join mechanik m on m.id_mech = n.id_mech
    where m.imie = name_p and m.nazwisko = surname_p;
    
           if cnt = 0 then   
                   raise NO_DATA_FOUND;
                end if;
            ...
         for k in kursor
          loop

【讨论】:

(很抱歉由于某种原因在答案中格式化代码时出现问题) 这些都不起作用。在这两种情况下,结果都是:过程 REDUCE_PRICE 编译的 PL/SQL 过程成功完成。 即使我的数据库中没有传递给过程的数据,我也没有引发任何异常:( 我虽然这可能是使用 sql developer 的问题,但我不这么认为,在更简单的程序中异常有效。 但是在我编译过程后我运行 reduce_price('param1','param2',3)。现在我看到,由于某种原因,即使我评论了几乎所有的行,即使我有“创建和替换”,程序也能正常工作。我会按照你说的检查调试器。

以上是关于有没有办法检查游标是不是返回没有记录?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 ref 游标是不是从 pl/sql 过程返回数据

通过游标从 mySQL 中选择记录返回 None 对象

oracle的游标cursor

简单记录一下日常会用到的游标

有没有办法检查子进程是不是仍在运行?

Javascript/Jquery-如何检查函数是不是返回任何值?