2012-02-05 141 views
2

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

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命令提示以下命令(后我已经调用集SERVEROUTPUT);

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

我得到以下输出;现在

Argument = Hello 
0 

PL/SQL procedure successfully completed. 

,如果我尝试直接从SQL *执行我的功能加上命令提示符下,使用下面的命令;

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 

任何对此的帮助将非常感激。

在此先感谢。

克雷格

回答

6

exec不与职能的工作,因为它不知道如何处理的返回值做。这与常规的PL/SQL语句相似;如果您调用函数,则必须将返回值分配给某个值。

如果你想使用的SQL * Plus的功能,您应该使用SQL来代替:

select tf('asdf') from dual; 

而且,你永远不应该在系统中创建对象。这可能会导致一些非常奇怪的问题。

+2

是真的,或者他也可以使用主机/绑定或本地变量在annon PL/SQL块获得返回值 – MStp 2012-02-05 05:09:44

3

从@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

+1是的,还有另一种方式,也可以像这样使用DECLARE rc数字(指定长度或使用%类型); arg varchar2(5):='Hello'; BEGIN rc:= tf(arg); DBMS_OUTPUT.PUT_LINE(rc); END;或者你也可以使用DBMS_OUTPUT.PUT_LINE(tf(arg));在开始和结束标签之间。 – MStp 2012-02-05 21:50:15

+0

@ MS Stp - 我以前的评论意味着你的意思;我认为值得把它分解成单独的答案,因为它本身是有用的,可以说更通用? – 2012-02-06 16:20:29