2010-05-27 33 views
2

我使用Oracle 10g編寫應用程序。在Oracle中調用字符串中的函數調用過程

我目前正面臨這個問題。我將「filename」作爲varchar2類型的參數。

filename可能包含的示例值是:'TEST || to_char(sysdate,'DDD')'。

在這個過程中,我想要得到這個文件名的值,如TEST147。 當我寫:

select filename 
into ffilename 
from dual; 

我得到的值ffilename = TEST || to_char(sysdate,'DDD')是有道理的。但我怎樣才能解決這個問題,並調用字符串值中的函數?

幫助讚賞。 謝謝。

回答

1

這是很容易的動態執行字符串...

create or replace function fmt_fname (p_dyn_string in varchar2) 
    return varchar2 
is 
    return_value varchar2(128); 
begin 
    execute immediate 'select '||p_dyn_string||' from dual' 
     into return_value; 
    return return_value; 
end fmt_fname; 
/

,問題就出現在您的字符串包含文字,與可怕的報價...

SQL> select fmt_fname('TEST||to_char(sysdate, 'DDD')') from dual 
    2/
select fmt_fname('TEST||to_char(sysdate, 'DDD')') from dual 
              * 
ERROR at line 1: 
ORA-00907: missing right parenthesis 


SQL> 

所以我們要逃避撇號,所有這些,包括你沒有包含在你發佈的字符串中的那些:

SQL> select * from t34 
    2/

     ID FILENAME 
---------- ------------------------------ 
     1 APC001 
     2 XYZ213 
     3 TEST147 


SQL> select * from t34 
    2 where filename = fmt_fname('''TEST''||to_char(sysdate, ''DDD'')') 
    3/

     ID FILENAME 
---------- ------------------------------ 
     3 TEST147 

SQL> 

編輯

只是爲了公平起見,我覺得我應該指出的是,託尼的解決方案效果一樣好:

SQL> create or replace function fmt_fname (p_dyn_string in varchar2) 
    2  return varchar2 
    3 is 
    4  return_value varchar2(128); 
    5 begin 
    6  execute immediate 'begin :result := ' || p_dyn_string || '; end;' 
    7   using out return_value; 
    8  return return_value; 
    9 end; 
10/

Function created. 

SQL> select fmt_fname('''TEST''||to_char(sysdate, ''DDD'')') from dual 
    2/

FMT_FNAME('''TEST''||TO_CHAR(SYSDATE,''DDD'')') 
-------------------------------------------------------------------------------- 
TEST147 

SQL> 

事實上,通過避免對DUAL的選擇它可能是更好的。

+0

通過SQL執行未經驗證的用戶輸入可能會導致SQL注入攻擊。使用SELECT至少可以提供一些保護,因爲它限制了函數的功能。允許PL/SQL注入會導致各種問題。 – 2010-05-27 23:40:34

2

您示例中的字符串值是無效的表達式;它應該是:'TEST'|| TO_CHAR(SYSDATE, 'DDD')

評價,你可以這樣做:那麼

execute immediate 'begin :result := ' || filename || '; end;' 
    using out v_string; 

v_string將包含 'TEST147'。

+0

感謝您的幫助。它正在生成值'TEST147',但它返回一個錯誤 dbms_output.put_line('Result:'|| v_string); 錯誤:PLS-00201:標識符'TEST147'必須聲明。 – DMS 2010-05-27 11:28:23

+0

我不明白。如果在立即執行前放入dbms_output.put_line(filename),你會得到什麼? – 2010-05-27 12:52:56

+0

遇到執行立即聲明時會拋出錯誤。 APC提供的另一種方法是可行的。謝謝你的時間。 – DMS 2010-05-27 13:05:22