【问题标题】:Inconsistent behaviour when executing a function from within Oracle SQL*Plus?从 Oracle SQL*Plus 中执行函数时行为不一致?
【发布时间】:2012-02-27 03:40:11
【问题描述】:

我是 Oracle 和 SQL 的新手,我正在尝试从 SQL*Plus 中执行一个简单的测试函数。我的函数称为 tf(用于测试函数),它在一个名为 tf.sql 的文件中定义如下;

create or replace
function
tf
(
 arg1 in varchar2
)
return number

as

return_value number;

begin

return_value := 0;
dbms_output.put_line('Argument 1 = ' || arg1);
return return_value;

end;
/

我可以使用以下命令成功将此函数加载到 Oracle 中;

SQL> start ./tf.sql

作为执行此命令的结果,SQL*Plus 只声明 ;

Function created.

当我从 SQL*Plus 命令提示符执行以下命令时(在我调用 set serveroutput on 之后);

SQL> exec dbms_output.put_line(SYSTEM.TF('Hello'));

我得到以下输出;

Argument = Hello
0

PL/SQL procedure successfully completed.

现在,如果我尝试直接从 SQL*Plus 命令提示符执行我的函数,请使用以下命令;

SQL> exec SYSTEM.TF('Hello');

然后我收到来自 SQL*Plus 的以下错误消息;

BEGIN SYSTEM.TF('Hello'); END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00221: 'TF' is not a procedure or is undefined
ORA-06550: ;ine 1, column 7
PL/SQL: Statement ignored

有人能帮我解释一下吗?我无法弄清楚为什么我的函数在第一种情况下似乎成功执行,但在第二种情况下却没有。

如果我从 SQL*Plus 命令提示符执行以下命令;

SQL> select * from user_objects where object_name = 'TF';

然后我得到以下结果;

OBJECT_NAME
-----------
TF
SUBOBJECT_NAME
--------------
OBJECT_ID
---------
74475
DATA_OBJECT_ID
--------------
OBJECT_TYPE
-----------
FUNCTION
CREATED
-------
05-FEB-12
LAST_DDL_
---------
05-FEB-12
TIMESTAMP
---------
2012-02-05:02:11:15
STATUS
------
VALID
T
-
N
G
-
N
S
-
N
EDITION_NAME
------------
1

对此的任何帮助将不胜感激。

提前致谢。

克雷格

【问题讨论】:

    标签: sql oracle function plsql


    【解决方案1】:

    exec 不适用于函数,因为它不知道如何处理返回值。这类似于常规的 PL/SQL 语句;如果你调用一个函数,你必须将返回值赋给某个​​东西。

    如果你想在 SQL*Plus 中使用函数,你应该使用 SQL:

    select tf('asdf') from dual;
    

    此外,您永远不应该在 SYSTEM 中创建对象。这可能会导致一些非常奇怪的问题。

    【讨论】:

    • True 或者他也可以在annon PL/SQL 块中使用host/bind 或局部变量来获取返回值
    【解决方案2】:

    从@jonearles 的回答开始,从 SQL*Plus 的角度突出了函数和过程之间的区别,以及@MS Stp 的评论,运行它的一种方法是:

    variable rc number;
    exec :rc := tf('Hello');
    
    Argument = Hello
    
    PL/SQL procedure successfully completed.
    

    要查看返回码,您可以这样做:

    print rc
    0
    

    exec 实际上只是匿名 PL/SQL 块的简写,正如您从收到的错误消息中看到的那样。 variable 允许您在 SQL*Plus 级别而不是在块中声明绑定变量。您还可以将参数声明为绑定变量,并使用单独的exec 调用进行设置:

    variable rc number;
    variable arg varchar2(5);
    exec :arg := 'Hello';
    exec :rc := tf(:arg);
    

    我经常使用这个结构来测试现有的过程调用,例如从 Pro*C 代码复制的东西,而不必用固定值替换该调用中的变量。它可以更轻松地使用不同的参数重复调用,并且您可以在多次调用中重用变量 - 因此您可以稍后将 :rc 传递给另一个函数。

    【讨论】:

    • +1 是的,还有另一种方式也可以像这样使用 DECLARE rc number(指定长度或使用 %TYPE); arg varchar2(5):='你好';开始 rc := tf(arg);DBMS_OUTPUT.PUT_LINE(rc);END;或者您也可以使用 DBMS_OUTPUT.PUT_LINE(tf(arg));在开始和结束标签之间。
    • @MS Stp - 我认为你之前评论的意思;我认为值得将其分解为一个单独的答案,因为它本身很有用,而且可以说更通用?
    猜你喜欢
    • 2011-07-04
    • 2019-11-09
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多