SQL过程返回太多行

时间:2015-11-27 07:52:32

标签: oracle plsql exception-handling

我创建了一个以pid作为参数并返回该pid的每月销售统计数据的过程,它使用两个表,产品和购买,其中购买中的pid是引用产品中的pid的外键。 该过程无错误地构建,并且仅针对单行返回执行良好,否则会给出too_many_rows异常 我的程序如下:

set serveroutput on
create or replace procedure try(
p_pid in purchases.pid%type) is
p_pname products.pname%type;
p_date varchar2(10);
p_qty_monthly number(5);
p_amnt_monthly number(7,2);
p_avg_price number(7,2);


begin
select pname, p_time, qty_month, amount_month,(amount_month/qty_month) as avg_sale into p_pname,p_date,p_qty_monthly, p_amnt_monthly, p_avg_price
FROM 
    (select p.pname, to_char(q.ptime,'MON yyyy') p_time, 
    sum(qty) as qty_month, sum(total_price) as amount_month 
    from products p, purchases q
    where p.pid=q.pid
and q.pid= p_pid
group by pname, to_char(q.ptime,'MON yyyy')); 
dbms_output.put_line ('Product name is:'|| p_pname || 'Purchase date is:' || p_date || 'Units sold per month are/is: ' || p_qty_monthly || 'Monthly sale amount: ' || p_amnt_monthly || 'Average sale price is: ' || p_avg_price);
end;
/
show errors

对于某些输入,它返回多行,如何使其打印所有行而不是给出too_many_rows异常?

4 个答案:

答案 0 :(得分:0)

  

ORA-01403:未找到数据

您在运行时获得 NO DATA FOUND 。您的过程代码没有任何问题,但是当您执行它时, SELECT..INTO 查询无法获取行 过滤谓词指定。

  

其中p.pid = q.pid

表格中没有 pid = 'p001'

的行

如果您确定错误,则可以添加no_data_found EXCEPTION 并捕获错误。

EXCEPTION 
   WHEN NO_DATA_FOUND THEN
      <do something>

答案 1 :(得分:0)

未找到任何数据意味着您的选择查询未返回&#39; p001&#39; p_id的。并且还要确保您的选择查询一次只返回一行,否则会引发错误。因为变量一次只能保存一个值。

// Create Job
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean(jobName);

// Create return codes mapper
SimpleJvmExitCodeMapper mapper = new SimpleJvmExitCodeMapper();

// Start Job
JobExecution execution = jobLauncher.run(job, new JobParameters());

// Close context
context.close();

// Map codes and exit
String status = execution.getExitStatus().getExitCode();
Integer returnCode = mapper.intValue(status);
System.exit(returnCode);

只需在结束语句之前添加例外块。

修改:您的带有p_pid检查的选择查询是

create or replace procedure m_pro(
        p_pid in products.pid%type) is
        p_pname products.pname%type;
        p_date purchases.ptime%type;
        p_qty_monthly purchases.qty%type;
        p_amnt_monthly purchases.total_price%type;
        p_avg_price purchases.total_price%type;


    begin
    select pname, p_time, qty_month, amount_month,(amount_month/qty_month) as avg_sale into p_pname,p_date,p_qty_monthly, p_amnt_monthly, p_avg_price
    FROM 
        (select p.pname, to_char(q.ptime,'MON yyyy') p_time, 
        sum(qty) as qty_month, sum(total_price) as amount_month 
        from products p, purchases q
        where p.pid=q.pid
    group by pname, to_char(q.ptime,'MON yyyy')) 
    where pname=p_pname;
    dbms_output.put_line ('Product name is:'|| p_pname || 'Purchase date is:' || p_date || 'Units sold per month are/is: ' || p_qty_monthly || 'Monthly sale amount: ' || p_amnt_monthly || 'Average sale price is: ' || p_avg_price);
    EXCEPTION
    WHEN no_data_found THEN
      dbms_output.Put_line ('No values returned');

    end;
    /

答案 2 :(得分:0)

如果您在该月没有购买任何商品,您的查询将无法返回任何数据,因此您收到的错误就是这样。 每个查询都需要返回一个结果,否则会出现错误ORA-1403未找到数据。

在您的情况下,您应该使用左连接,以便在该表中没有要加入的记录时始终从购买中获得记录。因此,在这种情况下,你的金额将为零。

答案 3 :(得分:0)

在我看来,你应该使用Ref游标来避免处理No Data Found或Too many Rows Exception时的任何担心。下面的片段会告诉你。

CREATE OR REPLACE PROCEDURE m_pro(
    p_pid IN products.pid%type,
    p_lst OUT sys_refcursor) -- Use ref cursor to avoid no data found or too many rows exception
IS
--  p_pname products.pname%type;
--  p_date purchases.ptime%type;
--  p_qty_monthly purchases.qty%type;
--  p_amnt_monthly purchases.total_price%type;
--  p_avg_price purchases.total_price%type;
BEGIN
  OPEN p_lst FOR 
  SELECT pname, 
  p_time, 
  qty_month, 
  amount_month, 
  (amount_month/qty_month)
AS
  avg_sale FROM
  (SELECT p.pname,
    TO_CHAR(q.ptime,'MON yyyy') p_time,
    SUM(qty)         AS qty_month,
    SUM(total_price) AS amount_month
  FROM products p,
    purchases q
  WHERE p.pid=q.pid
  GROUP BY pname,
    TO_CHAR(q.ptime,'MON yyyy')
  ) WHERE P.pid=p_pid;
END;