函数返回没有值

时间:2014-09-03 07:24:53

标签: sql oracle plsql

这是我设计的功能。它顺利完成了

CREATE OR REPLACE FUNCTION "F_CHECK"
(
    p_id IN VARCHAR2
    p_name IN VARCHAR2)RETURN VARCHAR2
    is 
    v_id VARCHAR2;
    v_name VARCHAR2;
    cnt pls_integer;
    BEGIN
        IF id IS NULL THEN
            RETURN NULL;
        END IF;
        SELECT COUNT(*) INTO cnt from emp_new where id = p_id;
        IF (cnt > 0) THEN
            SELECT id, name INTO v_id, v_name from emp_new where id=p_id;
        IF (v_id is null and p_id is null and v_name is null and p_name is null) THEN
            return NULL;    
        ELSE
            IF (v_name =trunc(p_name)) then
                return NULL;
            else
                insert into employees values(p_id,p_name,sysdate);
            end if;
        end if;
     end if;

    exception
    when DUP_VAL_ON_INDEX THEN
    raise application error (-20001, 'NAME EXISTS UNDER DIFFERENT ID');
    END F_CHECK;

但是当我执行函数

时,我没有得到预期的结果
select F_CHECK(1,1) from dual;

错误我得到的是:

SQL EEROR: ORA-06503: PL/SQL : FUNCTION RETURNED WITHOUT VALUE

3 个答案:

答案 0 :(得分:2)

执行流程到达时(第22行)

,您必须返回一个值
...
else
  insert into employees values(p_id,p_name,sysdate);
end if;
...

在这种情况下,函数不会返回调用者期望的值,因此会出错。

您可以指示PL / SQL编译器向您发出有关此类代码(以及其他问题)的警告 在编译之前ALTER SESSION SET PLSQL_WARNINGS='ENABLE:ALL';

答案 1 :(得分:1)

运行此代码时可能会导致异常的一个原因是:如果您的select into没有返回值,您将获得异常,一个nu处理异常

即使你在函数的末尾有一个返回NULL,但你仍然需要捕获可能发生的所有异常

您需要照顾的区域是:

SELECT id, name INTO v_id, v_name from emp_new where id=p_id;

围绕Begin ... EXCEPTION WHEN NO_DATA_FOUND THEN ... END;阻止

此外,如果您违反了表上的某些约束,您的insert语句可能会导致异常,因此您可能还需要处理它

查看Error Handling in Oracle

以下是您的更新代码,以及有关额外括号的固定代码

<强>被修改

CREATE OR REPLACE FUNCTION F_CHECK
(
    P_ID    EMP_NEW.ID%TYPE,
    P_NAME  EMP_NEW.NAME%TYPE
)
RETURN VARCHAR2 IS 
    V_ID      EMP_NEW.ID%TYPE;
    V_NAME    EMP_NEW.NAME%TYPE;
    CNT       NUMBER;
BEGIN

    --IF ID IS NULL THEN
    -- What is ID ?? is it P_ID
    --Changed below
    IF P_ID IS NULL THEN
        RETURN 'Error: Add Value For Id';
    END IF;

    IF P_NAME IS NULL THEN
        RETURN 'Error: Add Value For Name';
    END IF;

    SELECT 
        COUNT(*) INTO CNT FROM EMPLOYEES 
    WHERE ID = P_ID;

    IF (CNT > 0) THEN

        SELECT 
            ID, NAME INTO V_ID, V_NAME 
        FROM 
            EMP_NEW 
        WHERE 
           ID=P_ID;

        ----------------------------------------------------------------------------------------
        --IF V_ID IS NULL AND P_ID IS NULL AND V_NAME IS NULL AND P_NAME IS NULL THEN
        --The code above will always evaluate to False because P_ID at this stage is not null!
        --Also, if P_Name must have a value, check it at the begining along with the ID, not here
        ----------------------------------------------------------------------------------------

        IF V_ID IS NULL AND V_NAME IS NULL THEN
            RETURN 'Error: Not found details';      
        ELSE
            --Details are found
            IF (V_NAME = TRUNC(P_NAME)) THEN
                RETURN 'Name already assigned to this id';
            ELSE --Its a new name, add it
                INSERT INTO EMPLOYEES VALUES(P_ID,P_NAME,SYSDATE);
                --Make sure your columns are only three and in the correct order as the Values specified
            END IF;

        END IF;

    END IF;

    RETURN 'Ok, added';

    EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
            raise application error (-20001, 'NAME EXISTS UNDER DIFFERENT ID');
END F_CHECK;

答案 2 :(得分:1)

函数必须始终返回正确数据类型的值。否则,它会抛出以下错误

ORA-06503: PL/SQL: Function returned without value
Cause: A call to PL/SQL function completed, but no RETURN statement was executed.
Action: Rewrite PL/SQL function, making sure that it always returns a value of a proper type.

阅读ORA-06503: PL/SQL: Function returned without value

数据库版本:11.2.0.2.0

让我们看看这个错误的各种情况:

在函数体中没有 RETURN 语句且没有异常处理程序(最愚蠢的方式):

SQL> set serveroutput on    
SQL> CREATE OR REPLACE FUNCTION f_test(i_val NUMBER)
2 RETURN NUMBER AS
3 o_val NUMBER;
4 BEGIN
5 SELECT 100 / i_val
6 INTO o_val
7 FROM DUAL;
8 END;
9 /
Function created

SQL> select f_test(100) from dual;
select f_test(100) from dual
ORA-06503: PL/SQL: Function returned without value
ORA-06512: at "F_TEST", line 8

现在,在上面的代码中,数学逻辑是正确的,因此没有SQL错误来覆盖PL / SQL错误。让我们看看ORA-01476如何覆盖ORA-06503错误。

SQL> CREATE OR REPLACE FUNCTION f_test(i_val NUMBER)
2 RETURN NUMBER AS
3 o_val NUMBER;
4 BEGIN
5 SELECT 100 / i_val
6 INTO o_val
7 FROM DUAL;
8 END;
9 /
Function created

SQL> select f_test(0) from dual;
select f_test(0) from dual
ORA-01476: divisor is equal to zero
ORA-06512: at "F_TEST", line 5

嗯,这很明显,不是吗?

  1. 在异常处理程序中没有RETURN语句(最常见的错误):
  2.     
        SQL> CREATE OR REPLACE FUNCTION f_test(i_val NUMBER)
        2 RETURN NUMBER AS
        3 o_val NUMBER;
        4 BEGIN
        5 SELECT 100 / i_val
        6 INTO o_val
        7 FROM DUAL;
        8
        9 RETURN o_val;
        10
        11 EXCEPTION
        12 WHEN OTHERS THEN
        13 NULL;
        14 END;
        15 /
        Function created
    
        SQL> select f_test(0) from dual;
        select f_test(0) from dual
        ORA-06503: PL/SQL: Function returned without value
        ORA-06512: at "F_TEST", line 14
    

    现在让我们在所需的位置放置一个RETURN语句,代码应该可以正常工作而不会出现任何错误:

    SQL> CREATE OR REPLACE FUNCTION f_test(i_val NUMBER)
    2 RETURN NUMBER AS
    3 o_val NUMBER;
    4 BEGIN
    5 SELECT 100 / i_val
    6 INTO o_val
    7 FROM DUAL;
    8
    9 RETURN o_val;
    10
    11 EXCEPTION
    12 WHEN OTHERS THEN
    13 DBMS_OUTPUT.PUT_LINE('Came inside Exception handler');
    14 RETURN 0;
    15 END;
    16 /
    Function created
    
    SQL> select f_test(0) from dual;
    
    F_TEST(0)
    0
    Came inside Exception handler    
    

    底线是:

    • 函数必须始终返回正确数据类型的值,无论是正文还是异常。
    • 我们必须对错误做些什么而不仅仅是返回垃圾。我们必须升级/记录错误并处理它,对错误做一些事情,以便底层进程没有影响。
    • 最后,不要忘记,除了其他之外的异常; - &GT;本身就是代码中的一个错误,等待它破坏代码的机会。