2010-05-27 35 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