PL/SQL 应该有却找不到数据?

PL/SQL No data found even there should be?

我目前正在学习 PL/SQL atm,我 运行 遇到了一个家庭作业问题。

在下面的代码中,我正在获取一个省份的用户输入,并在游标声明中使用所述省份隔离 select 结果,并尝试 运行 visitsandtotal 过程,但我得到的是没有找到数据,为什么?

用户提示

SET SERVEROUTPUT ON

ACCEPT prov PROMPT 'Enter Province: ';

DECLARE
    customerprov   VARCHAR2(4000);
    customername   VARCHAR2(4000);
    visits         NUMBER;
    total          FLOAT;
    CURSOR prov_cursor is
    Select custprovince, custname
    into customerprov, customername
    from si.customer
    where upper(custprovince) = '&prov';
    
BEGIN
    for c in prov_cursor loop
        visitsandtotal(c.custname, visits, total);
        dbms_output.put_line('Name: ' || c.custname || ' Visits: ' || visits || ' Total Labor Cost: ' || total);
    end loop;
END;

程序

  CREATE OR REPLACE PROCEDURE visitsandtotal (
    userinput    IN  VARCHAR2
    , visits         OUT   NUMBER
    , total          OUT   FLOAT
) IS
BEGIN
    SELECT
        COUNT(*) AS visits
        , SUM(s.laborcost) AS totalcost
    INTO
    visits
    , total
    FROM
        si.customer   c
        INNER JOIN si.servinv    s ON c.custname = s.custname
    WHERE
        s.custname = userinput
    GROUP BY
        c.custname
        , s.custname ;

END;

错误

Error report -
ORA-01403: no data found
ORA-06512: at "S6_TRAN84.VISITSANDTOTAL", line 7
ORA-06512: at line 11
01403. 00000 -  "no data found"
*Cause:    No data was found from the objects.
*Action:   There was no data from the objects which may be due to end of fetch.

由于信誉度太低无法发表评论

NO_DATA_FOUND 错误来自您具有 where 子句和分组依据的过程..

如果没有带参数"userinput"的记录导致异常。

我建议更改程序,因为我们当然不需要按客户名称分组,因为客户名称是 where 子句的一部分;

CREATE OR REPLACE PROCEDURE visitsandtotal 
 (
    userinput IN  VARCHAR2
   ,visits    OUT NUMBER
   ,total     OUT FLOAT
) 
IS
BEGIN
  SELECT COUNT(*) AS visits
        ,SUM(s.laborcost) AS totalcost
  INTO   visits
        ,total
  FROM   si.customer c
  INNER  JOIN si.servinv s
  ON     c.custname = s.custname
  WHERE  s.custname = userinput;
  --removed  group by as custname is part of where clause  
END visitsandtotal;

但无论出于何种原因,如果您坚持保留 group by 子句,则必须在过程 visitsandtotal

中显式处理 NO_DATA_FOUND 异常
CREATE OR REPLACE PROCEDURE visitsandtotal 
 (
    userinput IN  VARCHAR2
   ,visits    OUT NUMBER
   ,total     OUT FLOAT
) 
IS
BEGIN
  SELECT COUNT(*) AS visits
        ,SUM(s.laborcost) AS totalcost
  INTO   visits
        ,total
  FROM   si.customer c
  INNER  JOIN si.servinv s
  ON     c.custname = s.custname
  WHERE  s.custname = userinput;
  GROUP  BY c.custname,s.custname;
  -- you dont need to mention custname from both table as join is in place
EXCEPTION 
  WHEN no_data_found THEN
    --HERE - write your exception code whatever you like to add
END visitsandtotal;