Sql 返回的函数没有值

Sql 返回的函数没有值,sql,oracle,plsql,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;

这就是我设计的功能。它得到了成功的遵守

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

运行此代码时可能出现异常的原因之一是:如果select into没有返回值,则会出现异常,即nu处理的异常

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

您需要关注的领域是:

SELECT id, name INTO v_id, v_name from emp_new where id=p_id;
Begin。。。当找不到数据时出现异常。。。结束

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

看看

下面是您的更新代码,也是关于附加括号的固定代码

已编辑

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;

运行此代码时可能出现异常的原因之一是:如果select into没有返回值,则会出现异常,即nu处理的异常

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

您需要关注的领域是:

SELECT id, name INTO v_id, v_name from emp_new where id=p_id;
Begin。。。当找不到数据时出现异常。。。结束

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

看看

下面是您的更新代码,也是关于附加括号的固定代码

已编辑

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;

当执行流到达(第22行附近)时,必须返回一个值

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

您可以指示PL/SQL编译器使用
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:ALL'

当执行流到达(第22行附近)时,必须返回一个值

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

您可以指示PL/SQL编译器使用
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:ALL'函数必须始终返回正确数据类型的值。否则,它将抛出以下错误

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.
阅读

数据库版本:
11.2.0.2.0

让我们看看此错误的各种场景:

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

现在,在上面的代码中,数学逻辑是正确的,因此没有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
这很明显,不是吗

  • 异常处理程序中没有返回语句(最常见的错误):
  • 底线是:

    • 函数必须始终返回正确数据类型的值,无论是从主体还是从异常返回
    • 我们必须处理错误,而不仅仅是返回垃圾。我们必须引发/记录错误并对其进行处理,对错误采取措施,以便底层流程不会受到影响
    • 最后,不要忘记,当其他人为空时会出现异常;–>它本身就是代码中的一个bug,等待机会破解代码

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

      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.
      
      阅读

      数据库版本:
      11.2.0.2.0

      让我们看看此错误的各种场景:

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

      现在,在上面的代码中,数学逻辑是正确的,因此没有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
      
      这很明显,不是吗

    • 异常处理程序中没有返回语句(最常见的错误):
    • 底线是:

      • 函数必须始终返回正确数据类型的值,无论是从主体还是从异常返回
      • 我们必须处理错误,而不仅仅是返回垃圾。我们必须引发/记录错误并对其进行处理,对错误采取措施,以便底层流程不会受到影响
      • 最后,不要忘记,当其他人为空时会出现异常;–>它本身就是代码中的一个bug,等待机会破解代码

      这不应该成功编译,当没有找到数据时,有一个额外的括号要添加
      ,并检查函数是否达到此异常。如果
      ,它也缺少一个
      结尾,这一点很重要;如果它在最后一个
      返回null
      之后,则可能会导致此错误,尽管它看起来应该在
      选择之后。请向我们展示您实际的、成功编译的函数。另外,如果您只返回null,为什么这是一个函数?为什么不把它变成一个过程?@AlexPoole在最后一个if循环中我提到了insert语句,它不应该成功编译,当没有找到数据时,有一个额外的括号来添加
      ,然后检查函数是否达到此异常。如果
      ,它还缺少一个
      结束,并且在哪里匹配很重要;如果它在最后一个
      返回null
      之后,则可能会导致此错误,尽管它看起来应该在
      选择之后。请向我们展示您实际的、已成功编译的函数。另外,如果您只返回null,为什么这是一个函数?为什么不将其设置为一个过程?@AlexPoole在最后一个if循环中,我提到了insert语句未经处理