Ошибка PLS-00103 при попытке извлечь из курсора - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь написать курсор. Я пытаюсь соответствовать синтаксису примеров, но всегда получаю ошибку компиляции в операторе FETCH.

CREATE OR REPLACE PROCEDURE IFSAPP.CLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS

     -- cursor to get all the purchase orders's that have lines in released state that 
    CURSOR c1 IS 
        SELECT DISTINCT PO.ORDER_NO
        FROM PURCHASE_ORDER PO, PURCHASE_ORDER_LINE_NOPART POLN
        WHERE PO.ORDER_NO = POLN.ORDER_NO 
        AND POLN.STATE = 'Released'
        AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY');

BEGIN

    DECLARE corder_no varchar2(12);

    OPEN c1;    
    LOOP
        FETCH c1 INTO corder_no;
        EXIT WHEN c1%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(corder_no);
    END LOOP;
    CLOSE c1;
END CLEAR_OLD_PURCHASE_ORDERS;
/
LINE/COL ERROR
-------- -----------------------------------------------------------------
17/9     PLS-00103: Encountered the symbol "FETCH" when expecting one of the following:
         constant exception <an identifier>
         <a double-quoted delimited-identifier> table columns long
         double ref char time timestamp interval date binary national
         character nchar
21/5     PLS-00103: Encountered the symbol "CLOSE" when expecting one of the following:
         end not pragma final instantiable order overriding static
         member constructor map

Кто-нибудь может увидеть, где я иду не так?

1 Ответ

0 голосов
/ 10 января 2019

Проблема на самом деле в том, что вы объявляете локальную переменную и используете ключевое слово DECLARE. Это запускает новый внутренний блок PL / SQL, но тогда у вас есть OPEN и т. Д. Без продолжения этого шаблона с новым BEGIN.

Тем не менее, вам не нужен субблок, просто переместите объявление локальной переменной выше существующего BEGIN и потеряйте лишние DECLARE:

CREATE OR REPLACE PROCEDURE IFSAPP.CLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS

     -- cursor to get all the purchase orders's that have lines in released state that 
    CURSOR c1 IS 
        SELECT DISTINCT PO.ORDER_NO
        FROM PURCHASE_ORDER PO, PURCHASE_ORDER_LINE_NOPART POLN
        WHERE PO.ORDER_NO = POLN.ORDER_NO 
        AND POLN.STATE = 'Released'
        AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY');

    corder_no varchar2(12);

BEGIN

    OPEN c1;    
    LOOP
        FETCH c1 INTO corder_no;
        EXIT WHEN c1%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(corder_no);
    END LOOP;
    CLOSE c1;
END CLEAR_OLD_PURCHASE_ORDERS;
/

Кстати, вы должны рассмотреть возможность использования синтаксиса соединения ANSI, а не древнего синтаксиса с разделителями-запятыми - FROM. И было бы проще использовать неявный цикл курсора:

CREATE OR REPLACE PROCEDURE IFSAPPCLEAR_OLD_PURCHASE_ORDERS (cPlannedDelDate in varchar2) IS
BEGIN
    FOR r1 IN (
        SELECT DISTINCT PO.ORDER_NO
        FROM PURCHASE_ORDER_LINE_NOPART POLN
        JOIN PURCHASE_ORDER PO
        ON PO.ORDER_NO = POLN.ORDER_NO 
        WHERE POLN.STATE = 'Released'
        AND POLN.PLANNED_DELIVERY_DATE < TO_DATE(cPlannedDelDate, 'DD/MM/YYYY')
    ) LOOP
        DBMS_OUTPUT.PUT_LINE(r1.order_no);
    END LOOP;
END CLEAR_OLD_PURCHASE_ORDERS;
/

Я бы также предпочел, чтобы аргумент процедуры был объявлен как необходимый вам тип данных, то есть как DATE, так что вы можете использовать его в своем запросе, не конвертируя его; и сделайте так, чтобы вызывающая сторона вставила правильный тип данных в.

...