SQL procedure returning too many rows

蓝咒 提交于 2019-12-25 18:47:19

问题


I've created a procedure that takes pid as parameter and returns monthly sale stats of that pid , it uses two tables, products and purchases where pid in purchases is foreign key referencing pid in products. The procedure builds without errors and executes well for only single row returns and otherwise give too_many_rows exception My procedure is as follows:

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

It's returning more than one rows for some inputs, how can I make it print all the rows rather than give too_many_rows exception?


回答1:


ORA-01403: no data found

You are getting NO DATA FOUND at run time. There is nothing wrong with your procedure code, but when you execute it, the SELECT..INTO query fails to fetch rows for the filter predicate specified.

where p.pid=q.pid

There are no rows in your table for pid='p001'

If you are sure about the error, then you could add no_data_found EXCEPTION and catch the error.

EXCEPTION 
   WHEN NO_DATA_FOUND THEN
      <do something>



回答2:


If you don't have any purchases in that month your query won't return any data, so the error you are receiving is a result of that. Each query needs to return a result or you get the error ORA-1403 No data found.

In your case you should use a left join so you always get a record back from purchases also when there are no records in that table to join with. So your sum will be zero in that case.




回答3:


no data found means your select query not returning any values for 'p001' p_id. And also make sure your select query should return only one row at a time otherwise it will throw an error. Because a variable will holds only one value at a time.

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;
    /

Just add exception block before end statement.

Edit: Your select query with p_pid check is

   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 and p.pid=(some value) -- in procedure p.pid=p_pid
        group by pname, to_char(q.ptime,'MON yyyy')) 
       -- where pname=p_pname remove where pname=p_name



回答4:


In my opinion you should use Ref cursor to avoid any kind of worry for handling No Data Found Or Too many Rows Exception. Below snippet will helo you.

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; 


来源:https://stackoverflow.com/questions/33952619/sql-procedure-returning-too-many-rows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!