Проверьте свои права и убедитесь, что вы указали явного владельца схемы в указанном вызове, используете синоним или подключитесь напрямую как владелец схемы.
Помните, что хранимые процедуры обычно выполняются с правами создателя кода, поэтому вам следует убедиться, что имя пользователя, которое вы используете для немедленного выполнения, имеет прямой доступ (не через роль) для выполнения функции.
Это прекрасно работает в Oracle 12c при входе в систему как владелец схемы:
create function myfunc(p_text in varchar2) return varchar2 is
begin
return initcap(p_text);
end;
/
begin
execute immediate 'update emp set ename = myfunc(ename)';
end;
/
select ename from emp;
Возвращает:
King
Blake
Clark
...
EDIT:
На основании дополнительной информации о том, что функция и вызывающая процедура находятся в одном пакете, вполне вероятно, что проблема заключается только в именовании и области действия.
При использовании execute immediate
оператор анализируется и выполняется во время выполнения механизмом Oracle Oracle с очень ограниченным контекстом окружающего кода.
Короче говоря, полезная нагрузка execute immediate
не знает, что он работает в пакете.
Вот демонстрация, которая должна немного прояснить ситуацию.
create or replace package mytest as
function public_func(p_text in varchar2) return varchar2;
procedure demo;
end;
/
create or replace package body mytest as
-------------------------------------------------------------------------------
function public_func(p_text in varchar2) return varchar2 is
begin
return initcap(p_text);
end;
-------------------------------------------------------------------------------
function private_func(p_text in varchar2) return varchar2 is
begin
return lower(p_text);
end;
-------------------------------------------------------------------------------
procedure demo is
begin
-- Test 1 should fail because the function name is not fully qualified
begin
execute immediate 'update emp set ename = public_func(ename)';
exception when others then
dbms_output.put_line('Test1: ' || SQLERRM);
end;
-- Test 2 should pass
begin
execute immediate 'update emp set ename = mytest.public_func(ename)';
exception when others then
dbms_output.put_line('Test2: ' || SQLERRM);
end;
-- Test 3 should fail because the private function is not visible
begin
execute immediate 'update emp set ename = mytest.private_func(ename)';
exception when others then
dbms_output.put_line('Test3: ' || SQLERRM);
end;
end;
end;
/
Вот результаты:
SQL> set serveroutput on;
SQL> begin
2 mytest.demo;
3 end;
4 /
Test1: ORA-00904: "PUBLIC_FUNC": invalid identifier
Test3: ORA-00904: "MYTEST"."PRIVATE_FUNC": invalid identifier
PL/SQL procedure successfully completed.
SQL>
В тесте 1 механизм SQL ищет что-то под названием public_func и не может его найти. Это имеет смысл, потому что вы можете иметь два пакета, в каждом из которых есть что-то с именем public_func. Механизм SQL не знает, что он вызывается из пакета.
Тест 2 - это то, что вы сделали, и он работает как положено.
Для теста 3 вызывается функция, которая существует только в теле пакета. Обычно другие процедуры в пакете могут видеть закрытые функции, но, поскольку это интерпретируется во время выполнения и механизм SQL не знает, что он вызывается в рамках пакета, этот вызов также завершается ошибкой.