【问题标题】:how to display error message for oracle nested cursor loops如何显示 oracle 嵌套游标循环的错误消息
【发布时间】:2015-04-25 14:10:30
【问题描述】:

我有一个项目,它创建一个过程并在参数中采用 Date 参数。执行该过程后,它会使用嵌套游标循环在“订单日期”列中显示订单 ID 和订单详细信息。我还试图显示我的订单表中不可用的日期的错误消息。 创建过程的代码如下

   create or replace procedure a05_order_details_by_date(p_order_date in date)
as
v_msg varchar2(400);
v_order_id ppl_order_headers.order_id%type;
v_order_date ppl_order_headers.order_date%type := p_order_date;

cursor cur_orders is
select order_id, order_date 
from ppl_order_headers
where extract(month from order_date) = extract(month from v_order_date) and
      extract(year from order_date) = extract(year from v_order_date) ;

cursor cur_order_details is
select ppl_order_details.plant_id, ppl_order_details.quantity, ppl_order_details.price, sum(ppl_order_details.quantity*ppl_order_details.price) as Extcost
from ppl_order_details
join ppl_order_headers on ppl_order_details.order_id = ppl_order_headers.order_id
where ppl_order_headers.order_id = v_order_id
group by ppl_order_details.plant_id, ppl_order_details.quantity, ppl_order_details.price; 

begin
<< order_loop >>
for rec_orders in cur_orders
loop
case
when (extract(month from v_order_date)) != (extract(month from rec_orders.order_date))
      and 
     (extract(year from v_order_date))!= (extract(year from rec_orders.order_date)) then
pr.pr('There are no orders for the requested month: ' || to_char(v_order_date, 'Month YYYY'));
else
pr.pr('Order ID' || '                   ' || 'Order Date'); 
v_order_id := rec_orders.order_id;
v_msg := rpad(v_order_id, 7) || '                    ' || rec_orders.order_date;
pr.pr(v_msg);
<< order_details >>
for rec_order_details in cur_order_details
loop
pr.pr('                           ' || '    Plant ID' || '    ' || 'Quantity' || '    ' || 'Price' || '    ' || 'ExtCost' );
 v_msg := '                                   ' || rec_order_details.plant_id || '          ' || rec_order_details.quantity ||
          '     ' || rec_order_details.price || '      ' || rec_order_details.Extcost;
pr.pr(v_msg);
end loop;
end case;
end loop;
end;
/

在数据集中给出日期时结果很好。但是当我尝试使用未来日期或不在数据集中的日期运行该过程时,它应该显示一条错误消息。但相反,它只显示“匿名块已完成”。

【问题讨论】:

  • 什么是pr.pr?它是应该为未来日期抛出错误的 PL/SQL 程序吗?您必须声明一个异常并明确raise它。
  • pr.pr 是为与 dbms_output.put_line 一样工作而创建的包。
  • 那么,你想要的输出是什么?执行 ELSE 部分时,您希望 pr 包打印错误消息。详细说明您的期望。
  • 基本上,如果参数中给出的日期在月份和年份中找到,则程序会显示每个订单及其详细信息。如果没有找到订单,那么我希望我的程序给出错误消息
  • 不要忘记,如果查询没有找到符合您条件的数据,那么循环内的代码将永远不会被执行!

标签: oracle error-handling cursor nested procedure


【解决方案1】:

您正在循环订单日期年/月与您的参数年/月匹配的订单;所以你的循环只包含匹配的数据。但是在那个循环里面你说:

case
when (extract(month from v_order_date)) != (extract(month from rec_orders.order_date))
      and 
     (extract(year from v_order_date))!= (extract(year from rec_orders.order_date)) then

首先,您可能的意思是“或”不是“和”,否则不同年份的同一月份仍然有效。但更重要的是,case 条件永远不会为真。由于光标的 where 子句,您处于一个循环中,该循环已经规定该记录的月份和年份必须与您的日期参数匹配。

所以这个case语句是多余的。如果游标找到任何数据,那么您将始终进入“else”子句。如果没有找到数据,那么您根本不会进入游标循环(正如 Tony Andrews 指出的那样),因此甚至不会评估此案例。

您可以通过计算循环中找到的记录数或设置布尔变量来生成消息;然后在循环后检查该状态:

...
  -- initial state is that we haven't seen any matching records
  v_record_found boolean := false;
begin
  << order_loop >>
  for rec_orders in cur_orders
  loop
    -- we have seen records matching the argument
    v_record_found := true;

    pr.pr('Order ID' || '                   ' || 'Order Date'); 
    v_order_id := rec_orders.order_id;
    ...
    << order_details >>
    for rec_order_details in cur_order_details
    loop
      pr.pr(...)
      ...
      pr.pr(v_msg);
    end loop;
  end loop;

  -- was the flag changed inside the loop?
  if not v_record_found then
    pr.pr('There are no orders for the requested month: '
     || to_char(v_order_date, 'Month YYYY'));
  end if;
end;

如果没有匹配的记录,您不会进入循环,并且标志永远不会更改为 true。但如果有匹配的记录,则设置为 true,并且不会显示“无订单”消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多