ORA-00904 - Неверный идентификатор в динамическом SQL - PullRequest
0 голосов
/ 21 октября 2019

Я пытаюсь докопаться до ошибки ORA-00904 - Invalid Identifier, которую я получаю в своей хранимой процедуре.

Вот код:

CREATE OR REPLACE PROCEDURE CDG4_HIER_GET_SUBTREE(pDimensionId IN VARCHAR2, pPeriodId IN NUMBER, pNodeId IN NUMBER, pMode IN CHAR, rCursor OUT SYS_REFCURSOR) IS

v_table_name VARCHAR2(30);
v_function_name VARCHAR2(30) := 'CDG4_HIER_MGR_HAS_CHILDREN'; -- some function defined in the same package
InvalidMode EXCEPTION;
---
v_sql VARCHAR2(2000);

BEGIN

-- Get dynamic table name
v_sql := 'SELECT UPPER(TABLE_ID)'
      ||'FROM CDG4_CFG_MAP_GER '
      ||'WHERE UPPER(DIMENSION_ID) = UPPER(''' || pDimensionId || ''') ';

EXECUTE IMMEDIATE v_sql INTO v_table_name;

IF pMode = 'F' THEN

    -- Do something

ELSIF pMode = 'S' THEN

    v_sql := 'SELECT A.PERIODO_K, '
           ||'      A.FIGLIO_K, '
           ||'      A.PADRE_K, '
           ||'      A.F_LAYOUT, '
           ||'      A.F_VISUALIZZA, '
           ||'      DECODE(A.PADRE_K, NULL, NULL, B2.CODICE) AS CODICE_PADRE, '
           ||'      A.F_ORDINE, '
           ||'      DECODE(A.GEN1, ''2'', ''I'', A.GEN1) AS GEN1, '
           ||'      A.GEN2, '
           ||'      A.GEN3, '
           ||'      ''[''|| B1.CODICE || ''] - '' || B1.DESCR AS DESCR, '
           ||'      ''[''|| B1.CODICE || ''] - '' || B1.DESCR AS DESCRIZIONE, '
           ||'      ' || v_function_name || '(''' || pDimensionId || ''', ' || pPeriodId || ', A.FIGLIO_K) AS HAS_CHILDREN '
           ||'FROM DM_GERARCHIE A, DIM_BO_CANALE_PRIMARIA B1, DIM_BO_CANALE_PRIMARIA B2 '
           ||'WHERE A.FIGLIO_K = B1.CODICE_K '
           ||'AND A.PADRE_K = B2.CODICE_K '
           ||'AND UPPER(A.DIMENSION_ID) = UPPER(''' || pDimensionId || ''') ' 
           ||'AND UPPER(B1.DIMENSION_ID) = UPPER(''' || pDimensionId || ''') ' 
           ||'AND UPPER(B2.DIMENSION_ID) = UPPER(''' || pDimensionId || ''') '
           ||'AND A.PERIODO_K = ' || pPeriodId
           ||' AND A.FIGLIO_K = ' || pNodeId;

ELSE 

    RAISE InvalidMode;

END IF;

OPEN rCursor FOR v_sql;

EXCEPTION
WHEN InvalidMode THEN
RAISE_APPLICATION_ERROR(-20005, 'Invalid selection mode.');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20004, 'Generic error - '||SQLCODE||' -ERROR- '||SQLERRM);

END;

Oracle, похоже, нетчтобы иметь возможность идентифицировать функцию v_function_name (она находится в том же пакете), поскольку она продолжает возвращать ORA-00904 при открытии курсора rCursor.

Есть ли какой-нибудь намек на правдоподобное предложение этого поведения?

Заранее спасибо.

1 Ответ

1 голос
/ 21 октября 2019

Похоже, что Oracle не может определить функцию v_function_name (она находится в том же пакете

Динамический SQL выполняется как SQL, но выходит за рамки пакета. Это означает, что нам нужно создать действительный оператор SQL. Если бы вы выполняли аналогичный статический оператор SELECT, вы бы написали package_name.v_function_name, потому что ваш SQL выполнялся бы вне пакета. И это то, что вам нужно сделать здесь.


Хотя сейчас я более внимательно изучил ваш код и вообще не понимаю, почему вы используете Dynamic SQL. Вы можете выполнять свои операторы как статический SQL с переменными и параметрами связывания.

OPEN rCursor FOR 
    SELECT A.PERIODO_K, 
           A.FIGLIO_K, 
           A.PADRE_K, 
           A.F_LAYOUT, 
           A.F_VISUALIZZA, 
           DECODE(A.PADRE_K, NULL, NULL, B2.CODICE) AS CODICE_PADRE, 
           A.F_ORDINE, 
           DECODE(A.GEN1, ''2'', ''I'', A.GEN1) AS GEN1, 
           A.GEN2, 
           A.GEN3, 
           '[' || B1.CODICE || '] - ' ||  B1.DESCR AS DESCR, 
           '[' || B1.CODICE || '] - ' || B1.DESCR AS DESCRIZIONE, 
            package_name.v_function_name (pDimensionId ,pPeriodId , A.FIGLIO_K) AS HAS_CHILDREN 
      FROM DM_GERARCHIE A, DIM_BO_CANALE_PRIMARIA B1, DIM_BO_CANALE_PRIMARIA B2 
      WHERE A.FIGLIO_K = B1.CODICE_K 
      AND A.PADRE_K = B2.CODICE_K 
      AND UPPER(A.DIMENSION_ID) = UPPER( pDimensionId )  
      AND UPPER(B1.DIMENSION_ID) =  UPPER( pDimensionId )  
      AND UPPER(B2.DIMENSION_ID) = UPPER( pDimensionId )  
      AND A.PERIODO_K = pPeriodId
      AND A.FIGLIO_K = pNodeId;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...