【问题标题】:Error when calling PL/SQL function调用 PL/SQL 函数时出错
【发布时间】:2017-10-27 22:08:07
【问题描述】:

我创建了一个 PL/SQL 函数,它应该借助我之前创建的 new_dept_new 序列将给定数量的记录添加到表中。函数编译成功。但是调用函数时出现错误:

BEGIN
dbms_output.put_line(myfunction3(3, 'OPERATIONS', 'NEW YORK'));
END;

Error report -
ORA-06503: PL/SQL: Function returned without value

功能:

CREATE OR REPLACE FUNCTION myfunction3(
records_count_in IN NUMBER, dept_name_in IN dept.dname%TYPE, loc_name_in IN dept.loc%TYPE)

RETURN INTERVAL DAY TO SECOND
IS 
thestart  TIMESTAMP := CURRENT_TIMESTAMP;
stopwatch INTERVAL DAY TO SECOND;
records_count NUMBER := records_count_in;
dept_name dept.dname%TYPE := dept_name_in;
loc_name dept.loc%TYPE := loc_name_in;

BEGIN
    FOR i IN 1..records_count LOOP
        INSERT INTO dept VALUES(new_dept_new.nextval, dept_name || TO_CHAR(new_dept_new.currval), loc_name || TO_CHAR(new_dept_new.currval));
COMMIT;
END LOOP;
    stopwatch := CURRENT_TIMESTAMP - thestart;
    DBMS_OUTPUT.PUT_LINE('Time for processing function: ');
RETURN stopwatch;
EXCEPTION WHEN OTHERS 
    THEN dbms_output.put_line('ERROR Processing Request for Department: ' || dept_name_in);
END;

为什么函数返回没有值?

编辑: 在收到来自 cmets 的反馈后,我编辑了函数,现在将值插入到表中并返回时间戳值。如果插入了 0 行,我还希望引发应用程序错误。

所以我做了以下事情:

CREATE OR REPLACE FUNCTION myfunction3(
records_count_in IN NUMBER, dept_name_in IN dept.dname%TYPE, loc_name_in IN dept.loc%TYPE)

RETURN INTERVAL DAY TO SECOND
IS 
thestart  TIMESTAMP := CURRENT_TIMESTAMP;
stopwatch INTERVAL DAY TO SECOND;
records_count NUMBER := records_count_in;
dept_name dept.dname%TYPE := dept_name_in;
loc_name dept.loc%TYPE := loc_name_in;

BEGIN
    FOR i IN 1..records_count LOOP
        INSERT INTO dept (deptno, dname, loc) 
        VALUES(new_dept_new.nextval, dept_name || TO_CHAR(new_dept_new.currval), loc_name || TO_CHAR(new_dept_new.currval));
    IF SQL%ROWCOUNT = 0 THEN
    raise_application_error (-20001, 'ERROR Processing Request for Department: ' || dept_name_in);
    END IF;
END LOOP;
    stopwatch := CURRENT_TIMESTAMP - thestart;
    DBMS_OUTPUT.PUT_LINE('Time for processing function: ');
RETURN stopwatch;
END;

但是,如果我调用这样的函数并插入零记录,我不会收到我的自定义错误消息。

BEGIN dbms_output.put_line(myfunction3(0, 'DEV_OPS', 'NEW YORK')); END;

我该如何解决这个问题?

【问题讨论】:

  • 更好的问题是,为什么我的函数编译成功,但它明显不正确? “显然”,因为不返回值的函数不可能是正确的。 期间。更好的问题的答案是exception 块。你永远不应该使用WHEN OTHERS THEN。结果是你的函数的任何错误都将被忽略,编译器会说“OK,成功编译”,而事实上函数可能充满了错误。不要难过;很多人都在做你做的事——但这并没有减少错误。
  • @mathguy 谢谢,我理解我的错误。我已经编辑了函数,以便将值插入到表中。我还添加了 IF SQL%ROWCOUNT = 0 THEN raise_application_error (-20001, 'ERROR Processing Request for Department: ' || dept_name_in);万一;就在 END LOOP 上方;但是,如果我调用这样的函数并插入零记录,我不会收到我的自定义错误消息。开始 dbms_output.put_line(myfunction3(0, 'DEV_OPS', 'NEW YORK'));结束;
  • 如何将records_count_in 传递为0 raise raise_application_error。它根本不会进入循环。不能这样模拟。仅当没有插入记录时,SQL%ROWCOUNT 才会设置为 0。

标签: sql oracle plsql


【解决方案1】:

除了exception 块之外,您的function 似乎没有任何问题。我能够使用您使用的表名和列名来模拟场景,并且效果很好。如果还有其他问题,例如缺少表、序列,它不会为您编译。所以,它失败的唯一原因是你的insert 声明。这可能是约束违规,值的长度超过列长度限制等。

您可以通过添加raise 语句对异常块进行轻微更改。这将帮助您识别调用程序中的实际错误。

EXCEPTION WHEN OTHERS 
    THEN dbms_output.put_line('ERROR Processing Request for Department: ' || dept_name_in);
RAISE;

另外,永远不要运行像

这样的插入语句
INSERT INTO dept VALUES (...)

这不是一个好的编码习惯,而且很难知道它将插入哪个顺序,尤其是当有很多列时。

始终明确提及列

INSERT INTO dept ( dept_id,dname,loc)  VALUES (..,..,..);

【讨论】:

  • 我已根据您的评论编辑了 INSERT 语句,现在将值插入到表中。但我也希望在插入 0 行时引发应用程序错误。所以我在END LOOP; 正上方添加了IF SQL%ROWCOUNT = 0 THEN raise_application_error (-20001, 'ERROR Processing Request for Department: ' || dept_name_in); END IF; 但是如果我调用这样的函数并且插入了零记录,我不会收到我的自定义错误消息。 BEGIN dbms_output.put_line(myfunction3(0, 'DEV_OPS', 'NEW YORK')); END;我该如何解决这个问题?
【解决方案2】:

您的函数中有一些异常导致您的函数遇到异常块。您的异常块中没有返回语句,因此出现错误。添加 RAISE 语句以查看导致异常的原因。

【讨论】:

    猜你喜欢
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多