为了避免不同的数据库表之间的不兼容性,并使ABAP/4程序能在应用中独立于数据库系统,SAP创建了一套叫作开放式SQL的独立SQL语句。开放式SQL包含了一套标准的SQL语句以及一些专用于SAP增强语句。使用开放式SQL,可以访问对SAP系统有效的任何数据库表,而不用考虑它的创建者。
开放式SQL关键字:
关键字 用途
SELECT 从数据库表读取数据
INSERT 向数据库表添加行
UPDATE 在数据库表中更改行
MODIFY 添加或更改行
DELETE 从数据库表中删除行
OPEN CURSOR,FETCH,CLOSECURSOR 使用光标从数据库表中读取行
COMMIT WORK,ROLLBACKWORK 确认或取消对数据库表的更改
SY-SUBRC:操作开放式SQL操作成功,SY-SUBRC为0,否则,不等于0.SY-DBCNT表示受该操作影响的行数,或已被处理的行数。
一、从数据库表读取数据
语法:
SELECT <result>FROM <source> [INTO<target>] [WHERE<condition>]
[GROUP BY <fields>][ORDER BY<sort_order>]
(1)选择多行的所有数据
SELECT [DISTINCT] * .....
......
ENDSELECT.
DISTINCT会自动去掉重复的行。如果至少读取了一行,系统字段SY-SUBRC就返回0.如没有读取,则返回4.系统字段SY-DBCNT给读取的行计数。每执行一次SELECT语句,SY-DBCNT都加1.
(2)选择单行的所有数据
语法:
SELECT SINGLE [FOR UPDATE] * ...... WHERE<condition> ......
该语句的结果是一个单行。为了保证清楚地指定了一行,就必须在WHERE子句的条件<condition>中用AND链接形成数据库主键的所有字段。FORUPDATE选项锁定在数据库表中选定的行。
例:
TABLE SPFLI.
SELECT SINGLE * FROM SPFLI WHERE CARRID EQ 'LH' AND CONNID EQ'2407'.
WRITE: / SPFLI-CARRID,SPFI-CONNID,SPFI-CITYFORM,SPFLI-CITYNO.
(3)为选定数据指定目标区
语法:
SELECT ... INTO<wa> ......
例:
TABLESSPFLI.
DATA WA LIKE SPFLI.
SELECT* FROM SPFLI INTO WA.
WRITE:/ WA-CITYFROM, WA-CITYTO.
ENDSELECT.
将数据读到内表中
SELECT ... INTO TABLE<itab>."将数据库表中行选择的结果集写入内表中,如果ITAB非空,数据会被覆盖
(4)在程序中为行选择指定条件
语法:
... WHERE <condition> ......
1. <f><opeartor><g>
如: WHERE CARRID = 'UA'; WHERE NUM GE 15. ; WHERE CITYFROM NE'FRANKFURT'.
2.<f> NOT BETWEEN<g1> AND<g2>
如:WHERE NUM BETWEEN 15 AND 45.; WHERE NUM NOT BETWEEN 1 AND 99.;
WHERE NAME NOT BETWEEN 'A' AND 'H'.
3.<f> NOT LIKE<g> [ESCAPE<h>] "该条件只能用于字符类型字段
_(下划线):表示单个字符
%(百分号):表示任意字符串,包括空字符串
如:
WHERECITY LIKE '%town%'.; WHERE NAMENOT LIKE '_n%'."第二个字母不为n的姓名。
WHERE FUNCNAME LIKE 'EDIT#_%' ESCAPE '#'. "所有以EDIT_开头的功能名称。
4.<f> NOT IN(<g1>,...<gn>)
如: WHERE CITY IN ('BERLIN','NEW YORK','LONDON'). WHERE CITY NOT IN('FRANKFURT','ROME').
5.指定条件的列表
语法: SELECT ... FROM ALL ENTRIES IN<itab> WHERE<condition> ...
该SELECT语句的结果集是SELECT语句的所有结果集的联合,这些结果集是用<ibab>中的相应值在每一行上替换占位符的结果。
注:数据库字段与内表中的关联比较字段必须具有相同的类型和长度。不要在数据库字段和表之段之间使用操作符LIKE,BETWEEN,和IN.如果使用了WHERE子句的该变式,就不要使用ORDER BY 子句。
二、更改数据库的内容
1、向数据库表添加行
添加一单行:
(1)INSERT INTO<dbtab> [CLIENT SPECIFIED]VALUES <wa>.
(2)INSERT<dbtab> FROM<wa>.
工作区<wa>中的内容将写进数据库表<dbtab>中。必须在程序中使用TABLES语句声明该数据库表。
2. 从内表中添加几行
语法:
INSERT<dbtab> [CLIENT SPECIFIED] FROM TABLE<itab> [ACCEPTING DUPLICATEKEYS].
如果在操作过程中因为主键冲突,加上ACCETPTINGDUPLICATE KEYS,它将跳过这些行而不插入,并将SY-SUBRC设置为4.但SY-DBCNT的值始终都为已插入行的数目。
3.在数据库表中更改行
如果因为不知道要插入行的主键是否已经存在,从而不能确定是否可使用UPDATE语句,那么,请使用MODIFY语句。MODIFY语句用于用更改现有的行和插入还不存在的行。
(1)更改单行
UPDATE <dbtab> [CLIENT SPECIFIED]FROM <wa>."工作区的内容将覆盖数据库表dbtab的行它们主键相同
UPDATE <dbtab> [CLIENTSPECIFIED]."没指定工作区,但表工作区<dbtab>中的内容将覆盖具有相同主码的数据库表的行
例:
TABLES SPFLI. "CARRID和CONNID是表SPFLI的主键
DATA WA LIKE SPFLI.
WA-CARRID = 'AA'.
WA-CONNID= '0064'.
WA-CITYFROM= 'WASHINGTON'.
UPDATE SPFLI FROM WA.
SPFLI-CARRID= 'LH'.
SPFLI-CONNID = '0017'.
SPFLI-CITFROM= 'BERLIN'.
UPDATE SPFLI.
以上代码将替换表SPFLI中所有主键为'AA','0064'和'LH','0017'的所有行。
(2)更改多行
语法:
UPDATE <dbtab> [CLIENT SPECIFIED] SET<S1>...<S2>[WHERE <condition>].
可以在SY-DBCNT中找到已改行的数目。如果至少更改了一行,SY-SUBRC就返回0.如果没更改任何行,就返回4.
(3)使用内表更改多行
UPDATE <dbtab> [CLIENT SPECIFIED]FROM TABLE<itab>."内表中行的长度至少要等于数据库表中行的长度。因为操作行集合更有效率,所以与操作单行相比,总是优先操作行集合。
TABLESSPFLI.
DATAITAB LIKE SPFLI OCCURS 10 WITH HEADER LINE.
IT-CARRID = 'UA'. ITAB-CONNID = '0011'.ITAB-CITYFROM = 'NEW YORK'.......
APPEND ITAB.
IT-CARRID = 'LH'. ITAB-CONNID = '1241'.ITAB-CITYFROM = 'BEIJING'.......
APPEND ITAB.
IT-CARRID = 'AA'. ITAB-CONNID = '4611'.ITAB-CITYFROM = 'ROME'.......
APPEND ITAB.
UPDATE SPFLI FROM TABLE ITAB.
该示例中,给内表ITAB定义了与数据库表SPFLI相同的结构,如果找到关键字相同的数据,就更改SPFLI中的数据。
(4)插入单行
语法:
MODIFY <dbtab> [CLIENTSPECIFIED] [FROM<wa>] ."将工作区<wa>中的内容写入数据库表中,将SY-SUBRC设置为0,将SY-DBCNT设置为1.如果工作区中的主键在数据库中没有则插入,有则更新数据表。
(5)插入多行
语法:
MODIFY <dbtab> [CLIENT SPECIFIED]FROM TABLE<itab>."内表中的行具有相同主码的行将被更新,没有的将被插入。SY-SUBRC设置为0,而SY-DBCNT设置为内表中的行数。
(6)从数据库中删除行
删除单行:
DELETE <dbtab> [CLIENT SPECIFIED]FROM<wa>."从数据表中删除与<wa>中主键相同的行。
DELETE <dbtab> [CLIENTSPECIFIED]."从数据库删除主键与表工作区<dbtab>中指定主键相同的行。
例:
TABLES SPFLI.
DATA WA LIKE SPFLI.
WA-CARRID = 'AA'.
WA-CONNID = '0064'.
DELETE SPFLI FROM WA.
SPFLI-CARRID = 'LH'.
SPFLI-CONNID = '0017'.
DELETE SPFLI.
(7)删除多行
语法:
DELETE FROM <dbtab> [CLIENTSPECIFIED] WHERE <conditions>.
使用内表删除多行
语法:
DELETE <dbtab> [CLIENT SPECIFIED]FROM TABLE<itab>."如果已处理了内表中所有行,SY-SUBRC置为0.否则为4.如内表为空,SY-SUBRC和SY-DBCNT都为0.
例:
TABLES SPFLI.
DATA ITAB LIKE SPFLI OCCURS 10 WITH HEADER LINE.
ITAB-CARRID= 'UA'. ITAB-CONNID = '0011'.
APPEND ITAB.
ITAB-CARRID = 'LH'. ITAB-CONNID = '1245'.
APPEND ITAB.
ITAB-CARRID = 'AA'. ITAB-CONNID = '4574'.
APPEND ITAB.
DELETE SPFLI FROM TABLE ITAB.
4、使用光标从数据库表中读取行
(1)打开光标
使用光标几乎可从任何SELECT语句的结果集中获得下一行(或一些行)。
语法:
OPEN CURSOR [WITH HOLD] <c> FORSELECT ... [WHERE <conditions>].
首先必须将光标<c>定义为类型CURSOR.如果使用WITHHOLD选项,那么在自身的SQL数据库提交之后,该光标将保留打开状态。
(2)用光标读取数据
在打开光标后,就可使用FETCH语句从OPENCURSOR语句生成的结果集中读取下一行(或一些行)。
语法:
FETCHNEXT CURSOR <c> INTO<target>.
如果FETCH语句没有读取任何行,SY-SUBRC就设置为4,否则为0。
(3)关闭光标
CLOSE CURSOR<c>.
下列情况将自动关闭光标:执行了COMMITWORK或ROLLBACK WORK语句时;当执行自身的SQL数据库提交或取消时;更改屏幕时;执行远程功能调用时。如果在OPENCURSOR语句中使用WITH HOLD选项,自身的SQL中的数据库提交不会关闭光标。
例:
TABLES SPFLI.
DATA: C1 TYPE CURSOR, C2 TYPE CURSOR.
DATA: WA1 LIKE SPFLI, WA2 LIKE SPFLI.
DATA: FLAG1, FLAG2.
OPEN CURSOR: C1 FOR SELECT * FROM SPFLI WHERECARRID = 'LH',
C2FOR SELECT * FROM SPFLI WHERE CARRID = 'AA'.
DO.
IF FLAG1 NE 'X'.
FETCHNEXT CURSOR C1 INTO WA1.
IF SY-SUBRC <> 0.
CLOSE CURSOR C1. FLAG1 = 'X'.
ELSE.
WRITE: / WA1-CARRID, WA1-CITYFROM, WA1-CITYTO.
ENDIF.
IF FLAG2 NE 'X'.
FETCH NEXT CURSOR C2 INTO WA2.
IF SY-SUBRC <> 0.
CLOSECURSOR C2. FLAG2 = 'X'.
ELSE.
WRITE: / WA2-CARRID,WA2-CITYFROM,WA2-CITYTO.
ENDIF.
IFFLAG1 = 'X' AND FLAG2 = 'X'. EXIT. ENDIF.
ENDDO.
5、确认或取消对数据库表的更改
COMMIT WORK/ROLLBACK WORK "使用COMMITWORK和ROLLBACKWORK语句的结果是将丢失所有的数据库光标。因此,在SELECT循环中或在处理SQL语句之前不允许使用这些语句。
例:
TABLES SPFLI.
DATA FLAG.
SPFLI-CARRID ='UA'.SPFLI-CONNID = '0011'. ...
INSERT SPFLI.
IF SY-SUBRC<> 0.
FLAG = 'X'.
ENDIF.
IF FLAG = 'X'.
ROLLBACK WORK.
ELSE.
COMMIT WORK.
ENDIF.
6、在ABAP/4程序的执行过程中锁定数据库对象
在SAP系统中,就用程序必须锁定它们使用的对象。这是因为每个程序都由两个任务组成:
对话任务,在该任务中输入或更改数据
更新任务,在该任务中更改数据库
对话任务将用户输入的数据传送给更新任务。然后更新任务读取取将修改的数据并相应地修改数据库。因为对话任务和更新任务是异步操作的,所以必须锁定所有涉及的对象,直到已成功地更改了数据库。在ABAP/4程序的执行过程中,必须锁定程序中的所有对象。
ENQUEUE/DEQUEUE
7、检查ABAP/4程序用户的权限
要在ABAP/4程序中检查用户权限,使用AUTHORITY-CHECK语句。
语法:
AUTHORITY-CHECK OBJECT'<object>'
ID '<name1>' FIELD<F1>
ID'<name2>' FIELD<F2>
......
ID'<name10>' FIELD<F10>.
<object>是即将检查的授权对象的名称。必须在ID后列出在<object>中定义的所有授权字段的名称(<name1>,<name2>...)。必须在<F1>,<F2>...中为即将检查的权限输入值以作为变量或字母。然后,该语句将为命名的对象搜索该用户的参数文件,以检查该用户是否有<f>中所有值的授权。然后SY-SUBRC将设置为0.
*&---------------------------------------------------------------------*
*& Form FRM_AUTH_CHECK
*&---------------------------------------------------------------------*
* 权限控制
*----------------------------------------------------------------------*
FORM FRM_AUTH_CHECK.
SELECT WERKS INTO TABLE IT_AUTH_CHECK FROM T001W WHERE WERKS IN S_WERKS.
LOOP AT IT_AUTH_CHECK.
AUTHORITY-CHECK OBJECT 'ZGQMM'
ID 'WERKS' FIELD IT_AUTH_CHECK-WERKS.
IF SY-SUBRC <> 0.
CONCATENATE '工厂 ' IT_AUTH_CHECK-WERKS '没有访问权限' INTO MSG.
MESSAGE MSG TYPE 'E'.
ENDIF.
ENDLOOP.
ENDFORM.
3