-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

这是您发布的第 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;

有多种方法可以打开和循环游标,并且您正在使用其中一种更明确的方法 - 这对于了解它们并不是一件坏事,但也要注意这些选项。

于 2015-11-11T20:01:14.947 回答