ABAP学习笔记之——第三章:OPEN SQL和NATIVE SQL

一、SAP R/3体系结构

        SAP R/3一个分为三层:数据库层、应用层、表示层。其中应用层和数据库层由一个系统构成。

表示层:表示层(Presentation Layer)简单来讲其实就是指个人PC,是保存构成SAPGUI(GraphicalUserInterface)的软件组件(Software Component)的机器。在这个层次提供 R/3 系统与用户之间的接口。SAPGUI是指安装在个人PC上的终端设备,用户就通过此设备输入或者查询数据。

应用层:SAP所有的程序都在应用层执行,SAP GUI只是起到终端的作用,运营服务器的应用层由一个或多个应用服务器与一个文档服务器(Message Server)组成。通过文档服务器与应用服务器相互连接,使用户自动选择符合小的服务器登录。其中可以使用多个应用服务器分散系统的负荷。SAP 中的应用层上存在本地缓冲器,若在 ABAP 数据字典中的数据库表上设置缓冲器,则不访问数据库层而直接在本地缓冲器中读取数据。这种设置可以提高SAP 性能,但只适用于 OPEN SOL。分配器(Dispatcher) 用于适当地分配工作流( Work Process

数据库层:数据库层(Database Layer) 与本章要学习的 SQL 语密切关系,SAP 中的所有数据都存储在这一层即数据库存储主数据,事务码以及 R/3 系统的所有数据。在应用层上创建用户与画面相互作用(Dialog)的 GU,它主要负责查询/维护数据库层的数据。在数据库层通过 DBMS 可以创建和管理如数据库表/视图/结构体等数据库对象。在这种环境下,开发者通过应用程序的 GU画面修改数据或者直接连接到数据库执行 SOL。

        SAP 禁止一般用户直接连接数据库修改数据,甚至有时还限制查询数据的权限。这种设置是为了保障数据的完整性、一贯性、安全性及透明性。当然,如果公开数据库的系统信息、ID 及密码就无法完全切断直接访问数据库的渠道。如图所示,ABAP 开发者通过ABAP数据字典管理数据库结构。

        ABAP 程序中使用的对象 (数据表、视图、结构体、类型等) 称为 ABAP 数据字典这些对象的信息叫 Metadata、Data Definition 或者 Schema,另外,通过这些ABAP 数据字典来定义及管理数据结构。 

二、OPEN SQL

读取数据:

 INTO:当查询一条数据时使用结构体、变量、工作区;当查询多条数据时使用内表,往内表插入数据是要使用append。

Package size:一次性读取n条数据。需要使用endselect语句。

From:

 Where:

例1(常规查询):

DATA:gt_itab TYPE STANDARD TABLE OF sflight,
     gs_wa   TYPE sflight.

*查询出来的结果放入结构体
SELECT * INTO gs_wa FROM sflight WHERE carrid = 'AA'.
  WRITE:/ gs_wa-carrid,gs_wa-connid.
ENDSELECT.
WRITE / '--------------------------------这里是分界线-----------------------------------'.
*查询结果用内表保存
SELECT * INTO TABLE gt_itab FROM sflight WHERE carrid = 'AA'.
LOOP AT gt_itab INTO gs_wa. "利用loop循环遍历输出
  WRITE:
  / gs_wa-carrid,gs_wa-connid.
ENDLOOP.

例2(动态sql-查询字段):

*动态SQL语句
DATA:gs_line(72) TYPE c,
     gt_list     LIKE TABLE OF gs_line(72).
gs_line = 'CARRID CONNID'.
SELECT DISTINCT (gs_line) INTO TABLE gt_itab
  FROM sflight WHERE CARRID = 'AA'.
IF sy-subrc = 0.
  LOOP AT gt_itab INTO gs_wa.
    WRITE: / gs_wa-carrid,gs_wa-connid.
  ENDLOOP.
ENDIF.

例3(package):

*package一次性取出n条数据循环输出
DATA NUM TYPE I VALUE 1.
SELECT carrid connid
  FROM spfli
  INTO CORRESPONDING FIELDS OF TABLE gt_itab
  PACKAGE SIZE 5.
  WRITE: / '第',NUM,'次取出的数据'.
  NUM = NUM + 1.
  LOOP AT gt_itab INTO gs_wa.
    WRITE: / gs_wa-carrid,gs_wa-connid.
  ENDLOOP.
ENDSELECT.

例4(动态使用数据库表名称):

*动态使用数据库名称
PARAMETERS p_tname TYPE char10.
DATA gs_wa TYPE sflight.

SELECT SINGLE * INTO gs_wa FROM (p_tname)
  WHERE carrid = 'AA'.
  WRITE:/ gs_wa-carrid,gs_wa-connid.

例5(INNER JOIN使用方法):

*INNER JOIN使用方法
TYPES: BEGIN OF t_str,
         carrid   TYPE sflight-carrid,
         carrname TYPE scarr-carrname,
       END OF t_str.
DATA:gs_str TYPE t_str.
SELECT SINGLE a~carrid b~carrname
  INTO CORRESPONDING FIELDS OF gs_str
  FROM sflight AS a
  INNER JOIN scarr AS b
  ON a~carrid = b~carrid
  WHERE a~carrid = 'AA'.
WRITE : gs_str-carrid,gs_str-carrname.

例6(outer join使用方法):

*outer join使用方法
TYPES : BEGIN OF t_str,
          carrid   TYPE sflight-carrid,
          carrname TYPE scarr-carrname,
        END OF t_str.
DATA:gs_str TYPE t_str.
SELECT SINGLE a~carrid b~carrname
  INTO CORRESPONDING FIELDS OF gs_str
  FROM sflight AS a
  LEFT JOIN scarr AS b
  ON a~carriD = b~carrid
  WHERE a~carrid = 'AA'.
WRITE: gs_str-carrid,gs_str-carrname.

例7(动态设置筛选条件):

*动态设置查询条件
DATA gs_where TYPE c LENGTH 72.
DATA gv_carrname TYPE scarr-carrname.
PARAMETERS carrid TYPE scarr-carrid.
CONCATENATE 'CARRID = ''' carrid '''' INTO gs_where. "拼接字符串:CARRID = 'AC'.
SELECT SINGLE carrname
  INTO gv_carrname
  FROM scarr
  WHERE (gs_where).
WRITE / gv_carrname.

例8(动态设置多个筛选条件):

*两个动态参数
TYPES : BEGIN OF gs_carr,    "自定义结构体
          carrid   TYPE scarr-carrid,
          carrname TYPE scarr-carrname,
        END OF gs_carr.
DATA gs_where TYPE c LENGTH 72.
DATA gt_where LIKE TABLE OF gs_where.
DATA gT_carr TYPE gs_carr.    "实例化结构体
PARAMETERS carrid1 TYPE scarr-carrid.
PARAMETERS carrid2 TYPE scarr-carrid.

CONCATENATE 'CARRID = ''' carrid1 '''' INTO gs_where.
APPEND gs_where TO gt_where.
gs_where = 'OR'.
APPEND gs_where TO gt_where.
CONCATENATE 'CARRID = ''' carrid2 '''' INTO gs_where.
APPEND gs_where TO gt_where.          "字符串拼接

SELECT *
  INTO CORRESPONDING FIELDS OF gT_carr "结果输出到结构体中(自动找到重名的字段进行赋值)
  FROM scarr
  WHERE (gt_where).
  WRITE: / gT_carr-carrid,gt_carr-carrname.
ENDSELECT.

例(在gui上执行sql语句):

PARAMETERS :p_sql(255) TYPE c.

DATA: go_sql TYPE REF TO cl_sql_statement.   "cl_sql_statement是一个类
DATA: gv_sql TYPE string.
DATA: gd_ret TYPE i.

CREATE OBJECT go_sql.
gv_sql = p_sql.

TRANSLATE gv_sql TO UPPER CASE.

CALL METHOD go_sql->execute_update     "execute_update是cl_sql_statement类的一个方法
  EXPORTING
    statement      = gv_sql   "输入SQL语句
  RECEIVING
    rows_processed = gd_ret.   "接收数据

WRITE: / '影响条数', gd_ret.

FOR ALL ENTRIES:FOR ALL ENTRY 语句与套 SELECT 语或 Subquery 的能相似。使用 FOR ALLENTRY 语句时,WHERE 语句中使用的条件必须是 itab 中存在的字段。

例:

*FOR ALL ENTRIES语句使用
DATA gt_spfli TYPE TABLE OF spfli.
DATA gt_sflight TYPE TABLE OF sflight.
DATA gs_sflight TYPE sflight.

SELECT * FROM spfli INTO TABLE gt_spfli.   "供下面做查询表用
SELECT * FROM sflight INTO TABLE gt_sflight
  FOR ALL ENTRIES IN gt_spfli   "从上面查询出来的数据作为表继续查询
  WHERE carrid = gt_spfli-carrid
  AND connid = gt_spfli-connid.

LOOP AT gt_sflight INTO gs_sflight.
  WRITE: / gs_sflight-carrid,gs_sflight-connid.
ENDLOOP.

 Group by:分组函数(having)

例:

*GROUP BY 语句使用
DATA:gv_carrid     TYPE sflight-carrid,
     gv_connid     TYPE sflight-connid,
     gv_paymentsum TYPE i.
SELECT carrid connid AVG( paymentsum )
  INTO (gv_carrid,gv_connid,gv_paymentsum)
  FROM sflight GROUP BY carrid connid.

  WRITE: / gv_carrid,gv_connid,gv_paymentsum.
ENDSELECT.

Order by:排序。用 ASCENDING升序,DESCENDING 降序

- 根据表的 KEY 值进行排序。

- 只适用于SELECT*语句。

- 在JOIN 语和视图中无法使用。

例:

*HAVING \ ORDER BY语句使用
SELECT carrid connid AVG( paymentsum ) AS pay
  INTO (gv_carrid,gv_connid,gv_paymentsum)
  FROM sflight GROUP BY carrid connid
  HAVING AVG( paymentsum ) > 40000
  ORDER BY pay.
  WRITE: / gv_carrid,gv_connid,gv_paymentsum.
ENDSELECT.

Subquery:利用 Subquery 可以在 WHERE 语句中追加特殊条件。Subquery 的 SELECT 语中只能指定一个字段。

例:

*SUBQUERY 用法
DATA:gv_carrid     TYPE sflight-carrid,
     gv_connid     TYPE sflight-connid,
     gv_paymentsum TYPE sflight-paymentsum.

SELECT SINGLE CARRID CONNID PAYMENTSUM
  INTO (gv_carrid,gv_connid,gv_paymentsum)
  FROM SFLIGHT AS A
  WHERE CARRID IN
  ( SELECT CARRID FROM SPFLI
    WHERE CARRID = A~CARRID AND CONNID = A~CONNID
  )
  AND A~CARRID = 'AA'.
  WRITE: / gv_carrid,gv_connid,gv_paymentsum.

 修改数据:

Insert:

插入一条数据:

插入多条数据:往数据库表一次性插入内表的所有值。插入相同主键的数据时会发生 dump error,为了避免发生这种错误要使用ACCEPTING DUPLICATE KEYS 语。INSERT 语执行失败系统变量SY-SUBRC会返回4。

例:

*插入多条数据
DATA : gt_spfli TYPE TABLE OF spfli,
       gs_spfli TYPE spfli.

gs_spfli-carrid = 'CN'.
GS_spfli-connid = '001'.
gs_spfli-cityfrom = 'Beijing'.
gs_spfli-cityto = 'Seoul'.
APPEND gs_spfli TO gt_spfli.

gs_spfli-carrid = 'CN'.
GS_spfli-connid = '002'.
gs_spfli-cityfrom = 'Beijing'.
gs_spfli-cityto = 'Busan'.
APPEND gs_spfli TO gt_spfli.

INSERT spfli FROM TABLE gt_spfli ACCEPTING DUPLICATE KEYS.

Update:

修改一条数据:

修改多条数据:

 例:

DATA gs_spfli TYPE spfli.
MOVE 'CN' TO gs_spfli-carrid.
MOVE '011' TO gs_spfli-connid.
MOVE 'shanghai' TO gs_spfli-cityfrom.
*一条数据
update spfli from gs_spfli.
UPDATE spfli SET cityto = 'beijing'
*多条数据
WHERE carrid = 'CN' AND connid = '001'.
IF sy-subrc = 0.
  WRITE 'update is success!!!'.
ENDIF.

Delete:

删除一条数据:

 删除多条数据:

例:

DATA gs_spfli TYPE spfli.

gs_spfli = 'CN'.

DELETE spfli FROM gs_spfli.

DELETE FROM spfli WHERE carrid = 'CN'.
IF sy-subrc = 0.
  WRITE 'delete success.'.
ENDIF.

Modify:

MODIFY 既有 UPDATE 功能也有INSERT功能。当数据库表中存在该值时会以主键为基准更新此数据,若不存在则会插入此数据。可以插入/更新一条或多条数据,<target>用于指定数据库表名字使用时还可以动态地定义。

一条数据:

多条数据:

例:

DATA:gt_spfli TYPE TABLE OF spfli,
     gs_spfli TYPE spfli.
*一条数据
gs_spfli-carrid = 'CN'.
gs_spfli-connid = '001'.
gs_spfli-cityfrom = 'BEIJING'.
MODIFY spfli FROM gs_spfli.
*多条数据
gs_spfli-carrid = 'CN'.
gs_spfli-connid = '001'.
gs_spfli-cityfrom = 'shanghai'.
APPEND gs_spfli TO gt_spfli.

gs_spfli-carrid = 'CN'.
gs_spfli-connid = '003'.
gs_spfli-cityfrom = 'shanghai'.
APPEND gs_spfli TO gt_spfli.

MODIFY spfli FROM TABLE gt_spfli.

 三、 NATIVE SQL

简介:OPEN SQL 不管使用任何数据库类型(Oracle、Informix、DB2 等),其语法都相同,而NATIVE SOL 随着数据库类型的不同其相应的 SQL 语也有所差异。NATIVE SOL 是适用于 Oracle 数据库的,因此若设置了 MS SOL等其他数据库的话就不能正常执行。在ABAP 程序中 NATIVE SOL 虽然没有 OPEN SOL 使用频繁,但是可以实现使用OPEN SQL 无法实现的复杂的 SQL 语句。

优点:可以访问 ABAP 数据库中没有的数据库表(Oracle 系统数据表等)。是依赖于数据库的SOL 语句,因此可以实现在 OPEN SOL中无法实现的 SOI

缺点:无法鉴定(Syntax Check)EXEC ~ ENDEXEC 之间的语法,因此常会发生 Dump Error。在使用不同数据库的系统中无法使用含有 NATIVE SQL 的ABAP 程序。在 SQL 语中一定要追加用于区分客户的 mandt 字段。

语法:

NATIVE SQL 随着使用不同的数据库类型其 SQL 语也有所差异。基本语句以 EXECSQL.开头、以ENDEXEC.结束。使用变量时要在变量名前追加冒号“.”,另外,NATIVE SOI中一定要追加区分客户的MANDT 字段。

 简单查询:

*简单查询
DATA: gv_carrid LIKE sflight-carrid VALUE 'AA',
      gv_connid LIKE sflight-connid.

"into要空格后再接冒号
EXEC SQL.
  select a.connid
    into :gv_connid
    from sflight a
    where a.mandt = :sy-mandt and a.carrid = :gv_carrid
ENDEXEC.

WRITE gv_connid.

 performing 用法:

TYPES: BEGIN OF t_str,
         carrid LIKE sflight-carrid,
         connid LIKE sflight-connid,
       END OF t_str.

DATA gt_itab TYPE TABLE OF t_str.
DATA gs_wa TYPE t_str.
DATA gv_carrid LIKE sflight-carrid VALUE 'AA'.

EXEC SQL PERFORMING append_itab.
  select a.carrid,a.connid
    into :gs_wa-carrid,:gs_wa-connid
    from sflight a
    where a.mandt = :sy-mandt
    and a.carrid = :gv_carrid
ENDEXEC.

FORM append_itab.
  WRITE: / gs_wa-carrid,gs_wa-connid.
  APPEND gs_wa TO gt_itab.
  CLEAR gt_itab.
ENDFORM.

多表连接:

TYPES: BEGIN OF t_str,
         carrid   LIKE sflight-carrid,
         connid   LIKE sflight-connid,
         carrname LIKE scarr-carrname,
       END OF t_str.
DATA gs_wa TYPE t_str.
DATA: gv_carrid LIKE sflight-carrid VALUE 'AA'.

EXEC SQL PERFORMING write_data.
  select a.carrid,b.carrname
  into :gs_wa-carrid,:gs_wa-connid
  from sflight a,scarr b
  where a.mandt = b.mandt
    and a.carrid = b.carrid
    and a.mandt = :sy-mandt
    and a.carrid = :gv_carrid
ENDEXEC.

FORM write_data.
  WRITE: / gs_wa-carrid,gs_wa-carrname.
ENDFORM.
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值