Приватная функция пакета внутри sql-запроса, содержащегося в публичной функции пакета

aleksandy
Дата: 24.11.2009 11:26:35
Есть в теле пакета функция внутри этой функции выполняется огромный запрос, состоящий из объедитения нескольких. Так вот в каждом из 3 подзапросов встречается конструкция CASE. Сейчас появилась необходимость добавить в результат запроса еще пару полей, среди которых нужно сделать точно такой же CASE, только по другому полю. Дабы не плодить одинаковый код я решил вынести CASE в отдельную функцию. И вот что я обнаружил: нельзя вместо CASE внутри SQL вызывать ни приватные функции пакета, ни подфункции вызывающей функции. Собственно, как бы это обойти без публичных функций пакета?
Вот схема того, что я выше написал:
CREATE OR REPLACE PACKAGE pkg
AS
FUNCTION my_function(
  <список_входных параметров>
) RETURN NUMBER;
END pkg;

CREATE OR REPLACE PACKAGE BODY pkg
IS
FUNCTION case_func(
  field_value IN NUMBER
) RETURN NUMBER
IS
BEGIN
  ...
END case_func;

FUNCTION my_function(
  <список_входных параметров>
) RETURN NUMBER
IS
BEGIN
  ...
  FOR rec (
    SELECT ...
        -- вот так сейчас есть
        , CASE WHEN NVL(some_table.field1, 0) = 0 THEN ... ELSE ... END
        , CASE WHEN NVL(some_table.field2, 0) = 0 THEN ... ELSE ... END
        /* вот так хотелось бы, но не получается
        , case_func(some_table.field1)
        , case_func(some_table.field2)
        */
        ...
        FROM ...
    UNION ALL
    SELECT ...
        -- вот так сейчас есть
        , CASE WHEN NVL(some_table.field1, 0) = 0 THEN ... ELSE ... END
        , CASE WHEN NVL(some_table.field2, 0) = 0 THEN ... ELSE ... END
        /* вот так хотелось бы, но не получается
        , case_func(some_table.field1)
        , case_func(some_table.field2)
        */
        ...
        FROM ...
    UNION ALL
    SELECT ...
        -- вот так сейчас есть
        , CASE WHEN NVL(some_table.field1, 0) = 0 THEN ... ELSE ... END
        , CASE WHEN NVL(some_table.field2, 0) = 0 THEN ... ELSE ... END
        /* вот так хотелось бы, но не получается
        , case_func(some_table.field1)
        , case_func(some_table.field2)
        */
        ...
        FROM ...
  ) LOOP
  END LOOP;
  ...
END my_function;

END pkg;
orawish
Дата: 24.11.2009 11:30:07
aleksandy,

обойти никак. вообще, имхо, зря вы от кейса решили отползать.
но если таки очень надо - пишите оператор
Elic
Дата: 24.11.2009 11:30:49
aleksandy
как бы это обойти без публичных функций пакета?
Никак.
aleksandy
Дата: 24.11.2009 11:41:48
orawish
вообще, имхо, зря вы от кейса решили отползать.

Просто каждый из кейзов - это порядка 50 строк, содержащими подзапросы, другие кейзы и прочее. И если надо что-то поправить, то править сейчас приходится в 3 местах. С учетом новых полей уже в 6. И вполне возможно, что позже придется добавить еще по паре таких кейзов :(

А запрос целиком и так уже порядка 500 строк и, кроме меня (т.к. я это дело писал), в нем никто с наскока не разберется, несмотря на подробные комментарии.
AlexFF__|
Дата: 24.11.2009 12:05:39
aleksandy,

Вам уже сказали, что проблема исключительно в
<< Собственно, как бы это обойти без публичных функций пакета?
Это что, так принципиально?
aleksandy
Дата: 24.11.2009 12:10:30
AlexFF__|
<< Собственно, как бы это обойти без публичных функций пакета?
Это что, так принципиально?

Открывать что-то во всеобщий доступ без необходимости - это нехорошо. А этой необходимости я тут не вижу. Так что, скорее всего, да, принципиально. :)

Я понял, что, как я хочу, сделать не получится. Поэтому оставлю кучу одинаковых кейзов.
aleksandy
Дата: 24.11.2009 12:14:23
Кстати, мне может кто-нибудь объяснить, почему так нельзя? С какой целью такие выкрутасы запрещены?
Elic
Дата: 24.11.2009 12:20:44
aleksandy
Кстати, мне может кто-нибудь объяснить, почему так нельзя? С какой целью такие выкрутасы запрещены?
SQL знает о PL/SQL-функциях лишь то, что есть в *_procedures, *_arguments.
Leshy
Дата: 24.11.2009 12:28:07
Возможно, динамический sql решит проблемы - Вы сможете иметь один кусок кода и у вас не будет вызовов pl/sql из sql. Но вы поимеете все проблемы динамического sql. Выбирайте.
hell
Дата: 24.11.2009 12:34:20
Elic
aleksandy
Кстати, мне может кто-нибудь объяснить, почему так нельзя? С какой целью такие выкрутасы запрещены?
SQL знает о PL/SQL-функциях лишь то, что есть в *_procedures, *_arguments.


Ну, вообще это pl/sql-ный sql, т.е. вполне мог бы и узнать...