ABAP 使用 Cursor 读取数据

举报
雨绸缪 发表于 2023/05/26 18:00:29 2023/05/26
【摘要】 在通常的 SELECT 语句中,所选内容中的数据始终在 SELECT 语句使用期间直接读入 INTO 子句中指定的目标区域(内表或者工作区)。但是使用 CURSOR 语句读取数据时,会将进程与 SELECT 语句分离,为此,必须打开 SELECT 语句的游标,之后可以将选中的行放置到目标数据中。语法:OPEN CURSOR [WITH HOLD] c FOR SELECT resu...

在通常的 SELECT 语句中,所选内容中的数据始终在 SELECT 语句使用期间直接读入 INTO 子句中指定的目标区域(内表或者工作区)。但是使用 CURSOR 语句读取数据时,会将进程与 SELECT 语句分离,为此,必须打开 SELECT 语句的游标,之后可以将选中的行放置到目标数据中。

语法:

OPEN CURSOR [WITH HOLD] c FOR SELECT      result
                                FROM      source
                                [WHERE    condition]
                                [GROUP BY fields]
                                [HAVING   cond]
                                [ORDER BY fields].

必须首先使用 DATA 语句和特殊数据类型 CURSOR 声明游标 c。您可以使用除 INTO 子句之外的 SELECT 语句的所有子句。此外,您只能表述 SELECT 子句,以便所选内容由多行组成。这意味着您不能使用 SINGLE 添加,并且列选择可能不包含仅聚合表达式。

打开的游标指向内部处理程序,类似于指向对象的引用变量。可以重新分配游标,以便将多个游标指向同一处理程序。在 MOVE 语句中,目标游标采用源游标的所有属性,即其位置和 OPEN CURSOR 语句中的所有子句。

还可以为单个数据库表并行打开多个游标。如果游标已打开,则无法重新打开它。若要显式关闭游标,请使用以下语句:

CLOSE CURSOR c.

应使用此语句关闭不再需要的所有游标,因为只能同时打开有限数量的游标。除了一个例外,数据库 LUW 在显式或隐式关闭游标时结束。OPEN CURSOR 语句中的 WITH HOLD 语句允许您防止在本机 SQL 中发生数据库提交时关闭游标。

读取数据

打开的游标链接到数据库表中的多行选择。要在 ABAP 程序中将数据读入目标区域,请使用以下命令:

FETCH NEXT CURSOR c INTO target.

这会将所选内容的一行写入目标区域目标,光标在选择集中进一步移动一行。FETCH语句将 INTO 子句与 SELECT 语句中的其他子句分离。您可以使用 SELECT 语句的所有 INTO 子句。该语句读取填充 INTO 子句的目标区域所需的行,并将光标移动到下一行。

如果未读取所选内容中的所有行,则 sy-subrc 设置为 0;否则,它设置为 4。在 FETCH 语句之后,系统字段 sy-dbcnt包含为相应游标读取的行数。

REPORT demo_select_cursor_1.

DATA: c1 TYPE cursor,
      c2 TYPE cursor.

DATA: wa1 TYPE spfli,
      wa2 TYPE spfli.

DATA: flag1(1) TYPE c,
      flag2(1) TYPE c.

OPEN CURSOR: c1 FOR SELECT  carrid connid
                      FROM  spfli
                      WHERE carrid = 'LH',

             c2 FOR SELECT  carrid connid cityfrom cityto
                      FROM  spfli
                      WHERE carrid = 'AZ'.

DO.
  IF flag1 NE 'X'.
    FETCH NEXT CURSOR c1 INTO CORRESPONDING FIELDS OF wa1.
    IF sy-subrc <> 0.
      CLOSE CURSOR c1.
      flag1 = 'X'.
    ELSE.
      WRITE: / wa1-carrid, wa1-connid.
    ENDIF.
  ENDIF.
  IF flag2 NE 'X'.
    FETCH NEXT CURSOR c2 INTO CORRESPONDING FIELDS OF wa2.
    IF sy-subrc <> 0.
      CLOSE CURSOR c2.
      flag2 = 'X'.
    ELSE.
      WRITE: / wa2-carrid, wa2-connid,
               wa2-cityfrom, wa2-cityto.
    ENDIF.
  ENDIF.
  IF flag1 = 'X' AND flag2 = 'X'.
    EXIT.
  ENDIF.
ENDDO.

输出如下的结果:

h-00100050000_image001.gif

数据库表 SPFLI 使用两个游标读取,每个游标具有不同的条件。所选行在 DO 循环中交替读取。

REPORT demo_select_cursor_2.

DATA c TYPE cursor.

DATA wa TYPE sbook.

OPEN CURSOR c FOR SELECT     carrid connid fldate bookid smoker
                    FROM     sbook
                    ORDER BY carrid connid fldate smoker bookid.

FETCH NEXT CURSOR c INTO CORRESPONDING FIELDS OF wa.

WHILE sy-subrc = 0.
  IF wa-smoker = ' '.
    PERFORM nonsmoker USING c.
  ELSEIF wa-smoker = 'X'.
    PERFORM smoker USING c.
    SKIP.
  ELSE.
    EXIT.
  ENDIF.
ENDWHILE.

FORM nonsmoker USING n_cur TYPE cursor.
  WHILE wa-smoker = ' ' AND sy-subrc = 0.
    FORMAT COLOR = 5.
    WRITE: / wa-carrid, wa-connid, wa-fldate, wa-bookid.
    FETCH NEXT CURSOR n_cur INTO CORRESPONDING FIELDS OF wa.
  ENDWHILE.
ENDFORM.

FORM smoker USING s_cur TYPE cursor.
  WHILE wa-smoker = 'X' AND sy-subrc = 0.
    FORMAT COLOR = 6.
    WRITE: / wa-carrid, wa-connid, wa-fldate, wa-bookid.
    FETCH NEXT CURSOR s_cur INTO CORRESPONDING FIELDS OF wa.
  ENDWHILE.
ENDFORM.

h-00100050000_image002.gif

程序将打开数据库表 SBOOK 的游标。在第一个 FETCH 语句之后,将调用一个子例程,该子例程取决于 SMOKER 列的内容。游标将传递到子例程中的接口参数。子例程读取更多行,直到 SMOKER 列的内容发生更改。子例程使用游标读取的行执行不同的任务。

REPORT demo_select_cursor_3.

DATA: wa_spfli   TYPE spfli,
      wa_sflight TYPE sflight,
      wa_sflight_back TYPE sflight.

DATA: c1 TYPE cursor,
      c2 TYPE cursor.

OPEN CURSOR c1 FOR     SELECT *
                 FROM  spfli
                 ORDER BY PRIMARY KEY.

OPEN CURSOR c2 FOR     SELECT *
                 FROM  sflight
                 ORDER BY PRIMARY KEY.

DO.
  FETCH NEXT CURSOR c1 INTO wa_spfli.
  IF sy-subrc NE 0.
    EXIT.
  ENDIF.
  WRITE: / wa_spfli-carrid, wa_spfli-connid.
  DO.
    IF NOT wa_sflight_back IS INITIAL.
      wa_sflight = wa_sflight_back.
      CLEAR wa_sflight_back.
    ELSE.
      FETCH NEXT CURSOR c2 INTO wa_sflight.
      IF  sy-subrc <> 0.
        EXIT.
      ELSEIF wa_sflight-carrid <> wa_spfli-carrid
          OR wa_sflight-connid <> wa_spfli-connid.
        wa_sflight_back = wa_sflight.
        EXIT.
      ENDIF.
    ENDIF.
    WRITE: / wa_sflight-carrid, wa_sflight-connid,
             wa_sflight-fldate.
  ENDDO.
ENDDO.

输出如下结果:

h-00100050000_image003.gif

程序为每个表 SPFLI 和 SFLIGHT 打开一个游标。由于两个表都通过外键关系链接,因此可以通过按主键对选择进行排序来对嵌套循环进行编程,以便内部循环中读取的数据依赖于外部循环中的数据。此编程方法比使用嵌套的 SELECT 语句更快,因为不必不断重新打开内部循环的游标。如果内部循环中存在控制级别更改,则读取数据将缓冲到下一个循环通过,因为无法重置游标。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。