2012-02-05 2 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 * 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 

Любая помощь по этому вопросу была бы чрезвычайно оценена.

Заранее спасибо.

Craig

ответ

6

exec не работает с функциями, потому что он не знает, что делать с возвращаемым значением. Это похоже на регулярный оператор PL/SQL; если вы вызываете функцию, вы должны назначить возвращаемое значение чему-либо.

Если вы хотите использовать функцию в SQL * Plus, вы должны использовать SQL вместо:

select tf('asdf') from dual; 

Кроме того, вы никогда не должны создавать объекты в системе. Это может вызвать некоторые действительно странные проблемы.

+2

True или он может также использовать host/bind или локальную переменную в блоке ANON PL/SQL для получения возвращаемого значения – MStp

3

Исходя из @jonearles ответа, который подчеркивает разницу между функцией и процедуры из SQL * Plus' точки зрения, и @MS комментарий StP в, так, чтобы запустить это:

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

Argument = Hello 

PL/SQL procedure successfully completed. 

Чтобы увидеть код возврата вы можете затем сделать:

print rc 
0 

exec действительно просто сокращенным для/SQL блока анонимного PL, как вы можете видеть из сообщения об ошибке вы получили. variable позволяет объявить переменную связывания на уровне SQL * Plus, а не в блоке. Вы также можете объявить аргумент как переменное связывание, и установить его с отдельным exec вызова:

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

Я часто использую эту конструкцию для тестирования существующего вызова процедуры, например, что-то скопировано из кода Pro * C, не заменяя переменные в этом вызове фиксированными значениями. Это может упростить вызов с разными аргументами, и вы можете повторно использовать переменные в нескольких вызовах - так что вы можете передать :rc другой функции позже.

+1

+1 Yup и существует другой способ, который также может использоваться как этот номер DECLARE rc (указать длину или использовать %ТИП); arg varchar2 (5): = 'Hello'; BEGIN rc: = tf (arg); DBMS_OUTPUT.PUT_LINE (rc); END; или вы также можете использовать DBMS_OUTPUT.PUT_LINE (tf (arg)); между начальными и конечными тегами. – MStp

+0

@MS Stp - это то, что, как я полагал, имел в виду из вашего предыдущего комментария; Я думаю, что стоит разобраться с этим в отдельный ответ, поскольку он полезен сам по себе и, возможно, более общий? –

Смежные вопросы