ABAP 使用 Cursor 读取数据
在通常的 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.
输出如下的结果:
数据库表 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.
程序将打开数据库表 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.
输出如下结果:
程序为每个表 SPFLI 和 SFLIGHT 打开一个游标。由于两个表都通过外键关系链接,因此可以通过按主键对选择进行排序来对嵌套循环进行编程,以便内部循环中读取的数据依赖于外部循环中的数据。此编程方法比使用嵌套的 SELECT 语句更快,因为不必不断重新打开内部循环的游标。如果内部循环中存在控制级别更改,则读取数据将缓冲到下一个循环通过,因为无法重置游标。
- 点赞
- 收藏
- 关注作者
评论(0)