编译 PLSQL 函数时出现“未找到数据”错误

Posted

技术标签:

【中文标题】编译 PLSQL 函数时出现“未找到数据”错误【英文标题】:"No Data found" error when compiling PLSQL Function 【发布时间】:2019-08-31 01:30:35 【问题描述】:

当尝试编译以执行这两个函数时(@directory),我在第 48 行(或函数的第 13 行)不断收到无数据错误。这是我收到的错误。注意:SYSTEM 是我连接的服务器。

ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "SYSTEM.DEPTPROJECT", line 13
ORA-06512: at line 4
ORA-06512: at line 4

这些是我的功能

SET ECHO ON;
SET FEEDBACK ON;
SET LINESIZE 100;
SET PAGESIZE 100;
SET SERVEROUTPUT ON;


CREATE OR REPLACE FUNCTION DEPTPROJECT(departmentNumber IN NUMBER)

RETURN VARCHAR IS
dep# DEPARTMENT.D#%TYPE;
depName DEPARTMENT.DName%TYPE;
counter NUMBER(10,0);
empNumber CHAR(5);
empName VARCHAR2(30);
result VARCHAR2(600);


BEGIN
SELECT D#, DNAME INTO dep#, depName FROM DEPARTMENT WHERE DEPARTMENT.D# = dep#;

result := result || 'Department'|| dep# || '' || depName || chr (10);


FOR i IN(SELECT  P# , PTitle , Budget FROM PROJECT WHERE PROJECT.D# = dep# ORDER BY BUDGET DESC)
LOOP
result:= result || chr(9)|| 'Project: ' || i.P# || '' ||  i.PTitle || i.Budget || chr(10); 

FOR j IN(SELECT  EMPLOYEE.Name, EMPLOYEE.E# FROM WORKSON INNER JOIN EMPLOYEE ON EMPLOYEE.E# = WORKSON.E# WHERE WORKSON.P# = i.P# ORDER BY EMPLOYEE.NAME ASC  )
LOOP
result:= result || chr(10) || j.E# || '' || j.Name || chr(10); 



END LOOP;
END LOOP;
RETURN result;
END;
/

BEGIN 
FOR x IN(SELECT D# FROM DEPARTMENT)
LOOP
DBMS_OUTPUT.PUT_LINE(DEPTPROJECT(x.D#));
END LOOP;
END;
/

【问题讨论】:

那些不是编译错误,它们是运行时错误。编译错误将以PLS- 开头。 SYSTEM 也不是服务器,它是一个帐户(您不应该将其用于开发)。此外,CHARVARCHAR 是非标准的 - 您应该使用 VARCHAR2 Oracle 在我们执行返回 no data 的 SELECT 语句时抛出 NO_DATA_FOUND 异常。也就是说,表中没有符合 WHERE 子句条件的行。您的代码有一个查询可能会抛出 NO_DATA_FOUND:来自 DEPARTMENT 的 SELECT。所以最可能的解释是您的 WHERE 子句使用变量 dep# - 这将是空值 - 而不是使用参数 departmentNumber 【参考方案1】:

当您选择 INTO 变量并且没有返回任何记录时,您应该收到 NO DATA FOUND 错误。我相信编写上述代码的正确方法是用它自己的 BEGIN/EXCEPTION/END 块包装 SELECT 语句。

例子:

SET ECHO ON;
SET FEEDBACK ON;
SET LINESIZE 100;
SET PAGESIZE 100;
SET SERVEROUTPUT ON;


CREATE OR REPLACE FUNCTION DEPTPROJECT(departmentNumber IN NUMBER)

RETURN VARCHAR IS
dep# DEPARTMENT.D#%TYPE;
depName DEPARTMENT.DName%TYPE;
counter NUMBER(10,0);
empNumber CHAR(5);
empName VARCHAR2(30);
result VARCHAR2(600);


BEGIN
SELECT D#, DNAME INTO dep#, depName FROM DEPARTMENT WHERE DEPARTMENT.D# = departmentNumber;

result := result || 'Department'|| dep# || '' || depName || chr (10);


FOR i IN(SELECT  P# , PTitle , Budget FROM PROJECT WHERE PROJECT.D# = dep# ORDER BY BUDGET DESC)
LOOP
result:= result || chr(9)|| 'Project: ' || i.P# || '' ||  i.PTitle || i.Budget || chr(10); 

FOR j IN(SELECT  EMPLOYEE.Name, EMPLOYEE.E# FROM WORKSON INNER JOIN EMPLOYEE ON EMPLOYEE.E# = WORKSON.E# WHERE WORKSON.P# = i.P# ORDER BY EMPLOYEE.NAME ASC  )
LOOP
result:= result || chr(10) || j.E# || '' || j.Name || chr(10); 

END LOOP;
END LOOP;
EXCEPTION
      WHEN NO_DATA_FOUND THEN
        result := 'Record Not Found';
RETURN result;
END;
/

BEGIN 
FOR x IN(SELECT D# FROM DEPARTMENT)
LOOP
DBMS_OUTPUT.PUT_LINE(DEPTPROJECT(x.D#));
END LOOP;
END;
/

【讨论】:

【参考方案2】:

我猜第 13 行应该使用传递给函数的变量:

SELECT D#, DNAME INTO dep#, depName FROM DEPARTMENT WHERE DEPARTMENT.D# = dep#;

应该是:

SELECT D#, DNAME INTO dep#, depName FROM DEPARTMENT WHERE DEPARTMENT.D# = departmentNumber;

【讨论】:

【参考方案3】:

您正在使用以下查询来获取 dep#depName 但您的 where 子句是 WHERE DEPARTMENT.D# = dep#

SELECT D#, DNAME INTO dep#, depName FROM DEPARTMENT WHERE DEPARTMENT.D# = dep#;

这里dep#是一个你已经声明但没有初始化的变量。

所以dep#nullNULL 的比较总是会导致错误,这意味着您的查询没有返回任何记录。

由于您在查询中使用了INTO,Oracle 正在从该查询中寻找一条记录,但它没有返回任何记录。因此,您正面临着这个问题。

根据您的逻辑,更改WHERE 子句以在比较中包含departmentNumber 或在查询中使用之前为dep# 分配适当的值。

另外,请确保将您的 SELECT .. INTO 查询包装在 BEGIN..EXCEPTION..END 中以避免此类动态异常。

干杯!!

【讨论】:

以上是关于编译 PLSQL 函数时出现“未找到数据”错误的主要内容,如果未能解决你的问题,请参考以下文章

尝试编译函数时出现语法错误

ff 创建时出现编译错误的函数

让 oracle 函数知道数据是不是为素数。收到警告:创建时出现编译错误的函数

调用递归函数时出现编译器错误 - “试图引用已删除的函数”

Typescript:更新 Firebase 函数依赖项时出现编译错误

使用继承构造函数时出现 VS2015 内部编译器错误