Вызов функции в строке в процедуре Oracle

Я пишу приложение, используя Oracle 10g.

Я сейчас сталкиваюсь с этой проблемой. Я беру в "имя файла" в качестве параметра типа varchar2.

Пример значения, которое может содержать имя файла: "TEST || to_char(sysdate, 'DDD')'.

В этой процедуре я хочу получить значение этого имени файла, как в TEST147. Когда я пишу:

select filename
into ffilename
from dual;

Я получаю значение ffilename = TEST || to_char(sysdate, 'DDD') имеет смысл. Но как я могу обойти эту проблему и вызвать функцию в строковом значении?

Помощь приветствуется. Благодарю.

2 ответа

Решение

Достаточно просто динамически выполнить строку...

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>

На самом деле, избегая SELECT на DUAL, это, вероятно, лучше.

Строковое значение в вашем примере является недопустимым выражением; должно быть: "ТЕСТ" || to_char (sysdate, 'DDD')

Чтобы оценить, что вы могли бы сделать это:

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

Тогда v_string будет содержать 'TEST147'.

Другие вопросы по тегам