文章目录
- 1. OPEN CURSOR 打开光标选数据
- 2. FETCH 获取光标后面的数据,按结果集大小,或者包大小
- 3. CLOSE CURSOR 关闭光标
- 4. 最后来看一个例子
1. OPEN CURSOR 打开光标选数据
首先它是和OPEN SQL的读取语法一起的。跟SELECT…END SELECT的循环平级。
就是对于一次性读取到内表数据量巨大的时候,给它设个读取数据量的大小限制,别让程序崩掉。
我主要是不知道这个语法具体怎么写:
具体的是:
OPEN CURSOR
FETCH
CLOSE CURSOR
这个语句就是给FOR以后的SELECT语句打开一个数据库光标,光标变量是dbcur。
那么到此呢,我去Select到的结果集,给放哪里呢?
还要组合FETCH去取。
2. FETCH 获取光标后面的数据,按结果集大小,或者包大小
那么dbcur是一个预定义的CURSOR类型变量。这里有个重要的点就是,你打开了这个数据库光标,那它不能被再次打开。
光标位置,也就是这个打开了的数据库光标就是结果集的第一行。
你的OPEN CURSOR语句之后,数据库光标就被放到结果集第一行的前面了。
在FOR后面,你要用一个SELECT语句,但是不要用INTO和APPENDING。 而且在SELECT 后面也不能加SINGLE。
注意,数据库光标同时刻不能开太多。开了的光标可以用CLOSE CURSOR这个语句关。
也可以用database commit 或者 database rollback来关。就是说COMMIT或ROLLBACK之后就会把光标关掉。
当然这个开了的数据库光标也是可以被其他程序调用,存储过程也可以调用它。一般不这么搞。
如果你用了OPEN CURSOR WITH HOLD。那么Native SQL的COMMIT就关不掉它。 也就是说COMMIT WORK这个语句关不掉它。ROLLBACK也关不掉它。
回到FETCH,它要提取结果集,需要用INTO 或APPENDING。从当前的光标的位置开始取。
这个FETCH后面的INTO或APPENDING必须得是和上面OPEN CURSOR 后的SELECT紧密关联的。
如果你INTO一个结构,那就只有一条数据哦。
如果INTO一个内表,那就是要么所有行都按选择条件取过去,要么是按照定义的PACKAGE SIZE来取的。
然后这个FETCH语句,把光标位置又移动到提取行的下一行去了。
如果没有下一行了,都取完了,那FETCH语句就把SY-SUBRC置为4 。就结束了。
而且这个FETCH语句还会设置两个系统变量的值:
- subrc
- sy-dbcnt
如果你取的结果集值溢出了,就是行数大于2147483647条。也就是一般的内表条目数大于20亿条的情况。
那么sy-dbcnt = -1
如果取不到值,那就是sy-dbcnt = 0.
例子: 从数据库表SPFLI读数据(用不同的数据包大小)
包大小由第一个光标用聚集count(*)来确定,第二个光标来访问。
DATA:BEGIN OF count_line,
carrid TYPE spfli-carrid,
count TYPE i,
END OF count_line,
spfli_tab TYPE TABLE OF spfli.
DATA: dbcur1 TYPE cursor,
dbcur2 TYPE cursor.
OPEN CURSOR dbcur1 FOR
SELECT carrid count(*) AS count
FROM spfili
GROUP BY carrid
ORDER BY carrid.
OPEN CURSOR dbcur2 FOR
SELECT * FROM spfli
ORDER BY carrid.
DO.
FETCH NEXT CURSOR dbcur1 INTO count_line.
IF sy-subrc<>0.
EXIT.
ENDIF.
FETCH NEXT CURSOR dbcur2
INTO TABLE spfli_tab PACKAGE SIZE count_line-count.
ENDDO.
CLOSE CURSOR: dbcur1,
dbcur2.
3. CLOSE CURSOR 关闭光标
这个语句就是关闭数据库光标,初始化光标值。
光CLEAR来初始化光标是不行的。
4. 最后来看一个例子
表SPFLI和SPLIGHT通过外键关联。
可以用个嵌套的LOOP,排序主键选择。系统会依据外部LOOP的条件读取内部LOOP的数据。这种方式会比嵌套SELECT的循环更高效。因为内部LOOP的光标不用被重置。
REPORT demo_select_cursor.
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.
CLOSE CURSOR: c1, c2.