-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 - 64bit Productionで作業しています。

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;
4

1 に答える 1

3

あなたが投稿したのは61行目ではなく、67行目です。この行は正しくありません:

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ループの反復から発生します。通常、カーソルをループする前に表示されると予想される行数はわかりません。

ここは特に知る必要はありません。カウント クエリは反復的です。同じデータをクエリしてから、カーソルを再度ヒットする必要があり、クエリ ロジックを 2 か所で維持する必要があります。カウントステップを忘れて、代わりにカーソルをループするときにカウンターを保持する方が簡単です。次に、ループ後にゼロ行条件を処理します。例えば:

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;

カーソルを開いてループするにはさまざまな方法がありますが、より明示的な方法の 1 つを使用しています。これは、カーソルについて学習するのに悪いことではありませんが、オプションにも注意してください。

于 2015-11-11T20:01:14.947 に答える