2012-02-05 65 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