oracle PL/SQL 存储函数 ORA-01422 和 ORA-06512

oracle PL/SQL stored function ORA-01422 and ORA-06512

我想编写一个 PL/SQL 存储函数,它将 driver 的员工编号作为参数,returns driver 的全名,城市他以嵌套形式访问过这座城市以及他访问过多少次 table。

我写了函数,编译成功。这是嵌套 table:

的代码
    CREATE OR REPLACE TYPE C_V 
AS OBJECT
(   FULLNAME VARCHAR(150),
    CITIES_VISITED VARCHAR(30),
    TOT_VISITS NUMBER(3)
);

CREATE OR REPLACE TYPE D_V_C
IS TABLE OF C_V;

函数如下:

CREATE OR REPLACE FUNCTION DRIVERVISITEDCITIES ( D_E# NUMBER)
RETURN D_V_C
IS
  D_FULLNAME VARCHAR(150);
  CITIES_VISITED_BY VARCHAR (30);
  TOTAL_VISITS NUMBER(3);

CITY_VIS_DETAIL D_V_C := D_V_C();

BEGIN

  CITY_VIS_DETAIL.EXTEND();
  SELECT DISTINCT EMPLOYEE.FNAME || EMPLOYEE.INITIALS || EMPLOYEE.LNAME AS FULLNAME,
       UPPER(TRIPLEG.DESTINATION),
       COUNT(TRIPLEG.DESTINATION)
  INTO 
        D_FULLNAME,
        CITIES_VISITED_BY,
        TOTAL_VISITS
FROM EMPLOYEE
INNER JOIN DRIVER
ON DRIVER.E# = EMPLOYEE.E#
INNER JOIN TRIP
ON TRIP.L# = DRIVER.L#
INNER JOIN TRIPLEG
ON TRIPLEG.T# = TRIP.T#
WHERE EMPLOYEE.E# = D_E#
GROUP BY EMPLOYEE.FNAME||EMPLOYEE.INITIALS||EMPLOYEE.LNAME, TRIPLEG.DESTINATION
ORDER BY COUNT(TRIPLEG.DESTINATION) DESC;
RETURN CITY_VIS_DETAIL;
END;

然而,当我尝试测试它显示的功能时:

Error starting at line 1 in command:
SELECT DRIVERVISITEDCITIES(1) FROM DUAL
Error report:
SQL Error: ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "SYS.DRIVERVISITEDCITIES", line 13
01422. 00000 -  "exact fetch returns more than requested number of rows"
*Cause:    The number specified in exact fetch is less than the rows returned.
*Action:   Rewrite the query or change number of rows requested

谁能帮我解决这个问题?

  SELECT DISTINCT EMPLOYEE.FNAME || EMPLOYEE.INITIALS || EMPLOYEE.LNAME AS FULLNAME,
       UPPER(TRIPLEG.DESTINATION),
       COUNT(TRIPLEG.DESTINATION)
  INTO 
        D_FULLNAME,
        CITIES_VISITED_BY,
        TOTAL_VISITS
FROM EMPLOYEE

您的查询正在返回多个值并将其存储到标量变量中。用您的对象类型变量替换标量变量并使用批量收集。

您已经定义了一个 collection 变量,但您没有填充它。相反,您 select 进入标量变量。很明显,您的查询 returns 不止一行(因为一个 driver 已经进行了不止一次旅行),这就是您得到 TOO_MANY_ROWS 异常的原因。

您需要 select 进入那个 collection。最简单的方法是使用 BULK COLLECT:

SELECT DISTINCT EMPLOYEE.FNAME || EMPLOYEE.INITIALS || EMPLOYEE.LNAME AS FULLNAME,
       UPPER(TRIPLEG.DESTINATION),
       COUNT(TRIPLEG.DESTINATION)
bulk collect into city_vis_detail  -- populate the collection like this
        D_FULLNAME,
        CITIES_VISITED_BY,
        TOTAL_VISITS
FROM EMPLOYEE
INNER JOIN DRIVER
ON DRIVER.E# = EMPLOYEE.E#
INNER JOIN TRIP
ON TRIP.L# = DRIVER.L#
INNER JOIN TRIPLEG
ON TRIPLEG.T# = TRIP.T#
WHERE EMPLOYEE.E# = D_E#
GROUP BY EMPLOYEE.FNAME||EMPLOYEE.INITIALS||EMPLOYEE.LNAME, TRIPLEG.DESTINATION
ORDER BY COUNT(TRIPLEG.DESTINATION) DESC;