PLS-00103: Обнаружен символ "1" при ожидании одного из следующих действий: (

Написал следующий сценарий PLSQL для создания отчета, и я получаю сообщения об ошибках

Error at line 5
ORA-06550: line 61, column 18:
PLS-00103: Encountered the symbol "1" when expecting one of the following:
   (

Я много раз просматривал код и не могу найти ошибку. Любая помощь будет принята с благодарностью. В настоящее время я работаю в Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64-битная версия

SET serveroutput ON size 1000000;

DECLARE
    TYPE TITLE_RECORD_TYPE IS RECORD
        (id                     number(19),
         gaid                   varchar2(20),
         artist_legal_name      varchar2(510),
         artist_display_title   varchar2(510),
         display_title          varchar2(510),
         category               varchar2(255),
         type                   varchar2(255),
         sub_type               varchar2(255));

    TITLE_RECORD            TITLE_RECORD_TYPE;

    v_title                     varchar2(510);
    v_artist                    varchar2(510);

    v_total_rows_error          number(20) := 0;
    v_row_count                 number(10) := 0;

    v_error_desc                varchar2(200) := NULL;
    v_error_code                number(19);

    CURSOR ARTIST_TITLE_CURSOR is
            select track_artist,track_title
            from asset_artist_title;

    CURSOR QUERY_CURSOR is
            select distinct g1.gaid,g2.legal_name,g1.artist_display_title,
                            g1.display_title,g1.category,g1.type,g1.sub_type
            from gcdm_app_rpt.rpt_asset g1,
                 gcdm_app_rpt.rpt_artist g2
            where g1.artist_id = g2.id
            and   g1.is_deleted <> 'Y'
            and   g1.is_core = 'Y'
            and   g2.is_core = 'Y'
            and   g1.title like v_title||'%'
            and   g1.artist_display_title like v_artist||'%';

BEGIN
    OPEN ARTIST_TITLE_CURSOR;

    LOOP
    FETCH ARTIST_TITLE_CURSOR into v_artist,v_title;
    EXIT WHEN ARTIST_TITLE_CURSOR%NOTFOUND or ARTIST_TITLE_CURSOR%NOTFOUND IS NULL;

    SELECT count(*)
    INTO   v_row_count
    FROM   gcdm_app_rpt.rpt_asset g1,
           gcdm_app_rpt.rpt_artist g2
    WHERE  g1.artist_id = g2.id
    AND    g1.is_core = 'Y'
    AND    g1.is_deleted <> 'Y'
    AND    g2.is_core = 'Y'
    AND    g1.title like v_title||'%'
    AND    g1.artist_display_title like v_artist||'%';


    IF v_row_count < 1 THEN
         v_error_desc := 'Matching Asset record for '||v_artist||' - '||v_title||' not found';
        DBMS_OUTPUT.PUT_LINE('Error: '||v_error_desc||'.');

         v_row_count := 0;
         v_total_rows_error := v_total_rows_error + 1;

    ELSE
        OPEN QUERY_CURSOR
        FOR i in 1..ARTIST_TITLE_CURSOR
        LOOP
        FETCH QUERY_CURSOR into TITLE_RECORD;
        EXIT WHEN QUERY_CURSOR%NOTFOUND or QUERY_CURSOR%NOTFOUND IS NULL;

        DBMS_OUTPUT.PUT_LINE(title_record.id,title_record.gaid,title_record.artist_legal_name,title_record.artist_display_name,
                             title_record.display_title,title_record.category,title_record.type,title_record.sub_type);

        END LOOP;
        CLOSE QUERY_CURSOR;

        v_row_count := 0;

    END IF;

    END LOOP;

    CLOSE ARTIST_TITLE_CURSOR;


    DBMS_OUTPUT.PUT_LINE(chr(0));

    IF v_total_rows_error > 0 THEN
        DBMS_OUTPUT.PUT_LINE('Total Rows in error: '||v_total_rows_error);

    END IF;

    DBMS_OUTPUT.PUT_LINE(CHR(0)); 

EXCEPTION
    WHEN OTHERS THEN
        v_error_desc := SQLERRM;
        v_error_code := SQLCODE;

    DBMS_OUTPUT.PUT_LINE('Error: '||v_error_desc||' - '||v_error_code);    

END;

1 ответ

Это строка 67 в том, что вы опубликовали, а не 61, но все же; эта строка не верна:

FOR i in 1..ARTIST_TITLE_CURSOR

Вы пытаетесь зациклить диапазон чисел - возможно, вы хотели получить количество записей, возвращаемых курсором, которое вы не можете получить - но ваш конечный "номер" является курсором, поэтому в данном контексте это недопустимо.

Но, похоже, все равно совершенно неуместно, когда вы перебираете QUERY_CURSOR записи, так что я не думаю, что ARTIST_TITLE_CURSOR актуален на данный момент. И вы не пытаетесь использовать i, Похоже, вы можете просто удалить эту строку.

Что еще более важно, в предыдущей строке отсутствует точка с запятой:

OPEN QUERY_CURSOR;

Потому что его нет, он видит FOR и ожидание запроса курсора.


Вслед за комментариями о том, почему у вас это FOR 1..v_row_countВсе еще немного избыточно. Вы ограничиваете количество выборок, которые вы делаете, чтобы соответствовать счетчику, который вы получили ранее, по сути, из того же запроса, что и у курсора, что означает, что вы не совсем когда-либо нажимаете EXIT WHEN QUERYCURSOR%NOTFOUND условие - это будет исходить из v_row_count+1 итерация цикла Обычно вы не знаете, сколько строк вы ожидаете увидеть, прежде чем зациклить курсор.

Вам не нужно знать здесь. Запрос подсчета является повторяющимся - вы запрашиваете те же данные, которые затем снова нажимаете для курсора, и вы должны поддерживать логику запроса в двух местах. Проще было бы забыть шаг подсчета и вместо этого держать счетчик, пока вы зацикливаетесь на курсоре; затем обработайте условие нулевых строк после цикла. Например:

DECLARE
...
BEGIN
  OPEN ARTIST_TITLE_CURSOR;
  LOOP
    FETCH ARTIST_TITLE_CURSOR into v_artist,v_title;
    EXIT WHEN ARTIST_TITLE_CURSOR%NOTFOUND;

    -- initialise counter for each ARTIST_TITLE
    v_row_count := 0;

    OPEN QUERY_CURSOR;
    LOOP
      FETCH QUERY_CURSOR into TITLE_RECORD;
      EXIT WHEN QUERY_CURSOR%NOTFOUND;

      -- increment 'found' counter
      v_row_count := v_row_count + 1; 

      DBMS_OUTPUT.PUT_LINE(title_record.id
        ||','|| title_record.gaid
        ||','|| title_record.artist_legal_name
        ||','|| title_record
        ||','|| artist_display_name
        ||','|| title_record.display_title
        ||','|| title_record.category
        ||','|| title_record.type
        ||','|| title_record.sub_type);

    END LOOP;
    CLOSE QUERY_CURSOR;

    -- now check if we found anything in the QUERY_CURSOR loop
    IF v_row_count < 1 THEN
      v_error_desc := 'Matching Asset record for '||v_artist||' - '||v_title||' not found';
      DBMS_OUTPUT.PUT_LINE('Error: Matching Asset record for '
        || v_artist || ' - ' || v_title || ' not found.');

      v_total_rows_error := v_total_rows_error + 1;
    END IF;
  END LOOP;
  CLOSE ARTIST_TITLE_CURSOR;

  --DBMS_OUTPUT.PUT_LINE(chr(0));
  -- presumably this was meant to put out a blank line; use this instead
  DBMS_OUTPUT.NEW_LINE;

  IF v_total_rows_error > 0 THEN
    DBMS_OUTPUT.PUT_LINE('Total Rows in error: '||v_total_rows_error);
  END IF;

  --DBMS_OUTPUT.PUT_LINE(CHR(0)); 
  DBMS_OUTPUT.NEW_LINE;
END;

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

Вам также не нужно объявлять ваш тип записи. В любом случае, вы можете использовать неявный курсор и полностью избежать типа и переменной, но даже с определением курсора, которое вы имеете, вы можете вместо этого поместить это:

TITLE_RECORD  QUERY_CURSOR%ROWTYPE;

Существуют различные способы открывать и циклически перемещаться по курсорам, и вы используете один из более явных - что неплохо узнать о них, но также следует учитывать варианты.

Другие вопросы по тегам