Получение ошибки при вызове любой функции в SQL-запросе в пакете без объявления функции в спецификации пакета

Я создал функцию, которая возвращает тип NUMBER в пакете, но не объявляет эту функцию в спецификации пакета.

Я вызываю эту функцию в SQL-запросе в другой функции с тем же телом пакета. Я получаю сообщение об ошибке.

Когда я объявляю функцию в спецификации пакета, тогда все в порядке и работает.

Я хочу знать причину этого. Пожалуйста, кто-нибудь объясните это.


person Bit_hunter    schedule 06.02.2013    source источник
comment
Не могли бы вы показать свои функции?   -  person Plouf    schedule 06.02.2013
comment
Извините, но этот вопрос не требует особых исследований и неясен. -1 за это.   -  person Rachcha    schedule 07.02.2013


Ответы (3)


Ничего общего с предварительным объявлением вообще.

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

Что касается причин, я могу только догадываться, так что не принимайте это как должное, но PL/SQL и SQL имеют разные механизмы. Таким образом, при выполнении SQL-запроса, даже внутри вашего пакета pl/sql, вы переходите на уровень SQL, где он снова проверяет разрешения в соответствии с механизмом SQL. Таким образом, он понятия не имеет, что он выполняется из пакета PL/SQL, и вам должно быть разрешено вызывать частную функцию.

Я думаю, что разницу в двигателях можно легко проверить, попробуйте использовать varchar2 из 32000, он будет работать в вашей функции pl/sql. Теперь, если вы вызовете функцию pl/sql, возвращающую varchar2(32000), произойдет сбой. Это проблема, с которой я столкнулся, но у меня нет базы данных, чтобы дать вам фрагмент.

person Plouf    schedule 07.02.2013
comment
Кажется, я неправильно понял вопрос ОП - я думал, что последовательность вызова была SQL -> function2 -> function1, тогда как он / она, вероятно, имел в виду function2 -> SQL -> function1. В данном случае вы правы, конечно. - person Frank Schmitt; 07.02.2013

Вы можете использовать функции, которые объявлены только в теле пакета, но вы должны объявить их до того, как они будут впервые использованы:

create or replace package pkg_so is

  function get2 return number;

end pkg_so;
/
create or replace package body pkg_so is

  function get1 return number is
  begin
    return 1;
  end;

  function get2 return number is
  begin
    return get1 + 1;
  end;

end pkg_so;
/
select pkg_so.get2 from dual
/
person Frank Schmitt    schedule 06.02.2013

да, это называется опережающим объявлением. Если какая-либо процедура/функция не объявлена ​​в пакете sepcificarion. Затем он должен быть сначала объявлен в теле до первого использования в теле.

create or replace package pkg_so is

  function get2 return number;

end pkg_so;
/
create or replace package body pkg_so is

  function get1 return number is
  begin
    return 1;
  end;

  function get2 return number is
  begin
    return get1 + 1;
  end;

end pkg_so;
/
select pkg_so.get2 from dual
/
person user2001117    schedule 06.02.2013