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;
Существуют различные способы открывать и циклически перемещаться по курсорам, и вы используете один из более явных - что неплохо узнать о них, но также следует учитывать варианты.