本章目录
- 概要
- OPEN SQL–读取数据
1 概要
1.1 R/3体系结构
学习SQL之前先了解一下R/3体系结构。如[图1]所示,SAP R/3一共分为三层结构。
其中应用层和数据库层由单独的系统构成。
1.表示层
表示层(Presentation Layer)简单来讲其实就是指个人PC,是保存构成SAPGUI (GraphicalUser Interface)的软件组件(Software Component)的机器。在这个层次提供R/3系统与用户之间的接口。SAP GUI是指安装在个人PC上的终端设备,用户就通过此设备输入或者查询数据。
- 应用层
SAP的所有程序都在应用层( ApplicationLayer)上执行,SAP GUI只是起着终端作用。
运营服务器的应用层由一个或多个应用服务器与一个文档服务器(Message Server)组成。
通过文档服务器与应用服务器相互连接,使用户自动选择符合小的服务器登录。其中可以使用多个应用服务器分散系统的负荷。SAP中的应用层上存在本地缓冲器,若在ABAP数据字典中的数据库表上设置缓冲器,则不访问数据库层而直接在本地缓冲器中读取数据。
这种设置可以提高SAP性能,但只适用于OPEN SQL。分配器(Dispatcher)用于适当地分配工作流( Work Process)。
3.数据库层
数据库层(Database Layer)与本章要学习的SQL语句密切关系,SAP 中的所有数据都存储在这一层即数据库存储主数据,事务码以及R/3系统的所有数据。例如,存储代表 R/3系统执行环境的系统变量,所有程序的代码及事务码数据等。
ABAP程序由代码、画面、函数、数据库表等项目组成,这些项目储存在R/3存储器中,用户在ABAP工作区中管理(创建/修改/查询)这些对象。如[图2]所示,JAVA、ASP、JSP等大部分程序语言的应用层与数据库层都是互相分离的。在应用层上创建用户与画面相互作用(Dialog)的GUI,它主要负责查询/维护数据库层的数据。
在数据库层通过DBMS可以创建和管理如数据库表/视图/结构体等数据库对象。在这种环境下,开发者通过应用程序的GUI画面修改数据或者直接连接到数据库执行SQL。
SAP禁止一般用户直接连接数据库修改数据,甚至有时还限制查询数据的权限。这种设置是为了保障数据的完整性、一贯性、安全性及透明性。当然,如果公开数据库的系统信息、ID及密码就无法完全切断直接访问数据库的渠道。如[图3]所示,ABAP开发者通过ABAP数据字典管理数据库结构。
1.2 SQL定义
SQL是Structured Query Language
的缩写,是在关系数据库中常使用的标准语言。
它共分为以下3种类型,在此3种类型中,ABAP程序的OPEN SQL里只允许使用DML语言。
- Data Manipulation Language (DML):处理数据的语言
-是用于查询,插入,删除,更新数据库数据的语言。
- Data Definition Language (DDL):定义数据的语言
-是应用程序与数据库管理系统之间传递数据的接口,一般用于创建数据库。
- Data Control Language (DCL):控制数据的语言
-是为了确保数据完整性、安全性及权限控制、恢复而使用的语言,一般用于保护数据。
1.3 SQL的种类
SQL语言包含OPEN SQL和 NATIVESQL两种。
OPEN SQL只有在ABAP语言中使用,通过数据库接口解析成NATIVE SQL后才能连接到数据库中。因此数据库中使用的SQL语言是NATIVE SQL。
1.4 OPEN SQL与NATIVE SQL
应用程序-数据库服务器的SQL流程器如图4所示。
- OPEN SQL
OPEN SQL是由创建数据库数据的ABAP命令构成的,在不同的DBMS(数据库管理系统)环境下其语法相同。OPEN SQL不能使用DDL、DCL,只能使用类似于SELECT
语句的DML语言。另外,还可以使用本地缓冲器,并且比 NATIVE SQL的使用方法简单。
ABAP程序有激活时自动执行Syntax Check的特点。
- NATIVE SQL
NATIVE SQL语言可以直接连接到数据库使用DML、DDL语言。
DDL语言可以直接创建/修改数据库表。还可以使用OPEN SQL的命令语句(SELECT
,UPDATE
、DELETE
等),并且无法用OPEN SQL解决的问题可以通过NATIVE SQL解决。
1.5 SQL与本地缓冲器
SAP本地缓冲器是R/3体系结构支持的技术,它主要负责减小数据库负荷。但是得在数据库表的技术设定里设置使用缓冲器。缓冲器的设置方法请参考“第7章ABAP数据字典”。
SELECT * FROM marc WHERE werks='1101'
IF SY-SUBRC EQ 0.
WRITE marc.
EXIT.
ENDIF.
ENDSELECT.
上面所示的SQL语句运行顺序如[图5]所示。
下面分析[图3-5]所示的SQL执行顺序。
①执行从数据库表MARC中查询WERKS='1101'
数据的SQL语句。
②在数据库接口OPEN SQL被解析成NATIVE SQL,再从数据库表 MARC 中查询WERKS字段值为‘1101’的数据。
③数据库表MARC中存在3件WERKS='1101'
的数据,这3件数据保存在本地缓冲器中。SQL语句SY-SUBRC EQ '0'
.即是指从数据库中取得数据的语句执行成功,然后执行EXIT语句跳出F语句,显示第一个值为’1101’的数据。
重新执行SQL语句时由于本地缓冲器中已经存在WERKS = '1101'
的数据,因此不用再次访问数据库,直接在本地缓冲器中就可以取得数据。
1.6 OPEN SQL概要
OPEN SQL是 R/3系统使用的语言,有查询/修改数据库数据的功能。它与使用的数据库系统(Oracle、MSSQL、Max DB等)无关,SQL执行结果都一样。它适用于ABAP数据字典中创建的数据库表、视图,只能执行第7章中要学习的Cluster 以及Pooled数据库表中限制的功能。OPEN SQL普遍依赖于客户(Client)。
在[图6]中可以看出R/3系统是由多个独立的客户(例如一个集团所属的个别法人)组成的。数据库表是依赖于客户独立存在(Client-independent)的对象,因此即使在100客户中创建的数据库表,200、300客户中也同样存在,但是100客户的数据库表中生成的数据只存
在于100客户中。若在ABAP数据表中不存在 MANDT字段,则数据库表数据就有依存于客户的属性。若表里不存在 MANDT字段,则表就拥有 Client-independent属性。如[图3-6]所示,实际数据库表都将客户信息保存在字段MANDT 中。
OPEN SQL里经常使用的命令如[表1]所示。所有OPEN SQL执行成功都会返回系统变量SY-SUBRC
为0(失败则返回0以外的值),系统变量SY-DBCNT
返回数据的个数。
关健字 | 功能 |
---|---|
SELECT | 从数据库表中读取数据 |
INSERT UPDATE | 往数据库表中追加数据 修改数据库表的数据 |
MODIFY | 执行INSERT+UPDATE功能 UPDATE:数据库表中已存在此数据时(以key值区分是否存在)INSERT:数据库表中不存在此数据时(以 key值区分是否存在) |
DELETE | 删除数据库表数据 |
表1 OPEN SQL命令语句
2 OPEN SQL——读取数据
从数据库表中读取数据的语句如[表2]所示。首先学习各个语句的功能定义,再通过练习掌握其具体使用方法。
语句 | 功能 |
---|---|
SELECT | SELECT语句可以罗列数据库表字段,读取一件或多件数据 |
INTO | INTO语句用来指定查询出来的数据存储地即变量,然后在程序中使用此变量 |
FROM | FROM语句用来指定要查询的数据库表。可以写在INTO语句前后 |
WHERE | 可以限制要查询数据的条件 |
GROUP BY | 用于分组查询数据。例如,分组求合计时经常使用GROUP BY语句 |
HAVING | HAVING是用于限制GROUP BY条件的语句。 |
ORDER BY | 类似于SELECT的WHERE语句用于排序(sort)查询的数据 |
表 2
2.1 SELECT语句
SELECT
语句从数据库表中读取必要的数据。
**SELECT**
SELECT语句分为俩个部分。一部分为,用于指定查询数据的件数,当查询一件时用 SINGLE
语句。另一部分是<columns
>,用于指定要查询的数据库表字段。
SELECT …
- 一条数据
从数据库中取得一条数据时使用SINGLE
语句。使用此语句只会取得一条数据,因此要正确给出要查询数据的条件。即在WHERE
条件里追加所有 key
值,当没有指出所有 key
值时,会返回多件中的任意一件,会导致读取的数据与预期结果不同。读取数据库表所有字段时使用*。
SELECT SINGLE …WHERE
- Several Line
当取得多条数据时SELECT
结果会保存到内部定义的表中。这种表在 ABAP
语言里称为内表(Internal Table)。内表会在第5章中详细说明(内表是ABAP内存中生成的存储数据的虚拟表)。DISTINCT
语句用于删除重复值。
SELECT [DISTINCT] …WHERE
INTO
语句的结果不是保存到内表,而是字段或者结构体(Work Area…)时,最后要加ENDSELECT
语句。这种语句相当于在LOOP
循环中执行SELECT
语句,每取出一条数据,就把它追加到结构体中,一直到读取全部符合条件的数据为止。
SELECT[DISTINCT] … WHERE …
ENDSELECT.
REPORT Z0_01.
DATA:gt_itab TYPE STANDARD TABLE OF sflight,
gs_wa TYPE sflight.
SELECT * INTO gs_wa FROM sflight
WHERE carrid EQ 'LA'".
WRITE: / gs_wa-carrid,
gs_wa-connid.
ENDSELECT.
DATA: gt_itab TYPE STANDARD TABLE OF sflight,
gs_wa TYPE sflight.
SELECT * INTO TABLE gt_itabFROM sflight
WHERE carrid EQ 'AA'.
LOOP AT gt_itab INTO gs_wa.
WRITE: / gs_wa-carrid,
gs_wa-connid.
ENDLOOP.
- AS(别名)
利用AS语句可以给字段指定别名。
SELECT[AS]…
- 动态
**SELECT**
语句
可以动态定义SELECT
语句的字段。保存动态语句的结构体GS_LINE
最多可以容纳72位CHAR
类型。结构体GS_LINE
为null
时与*语句相同。
SELECT () …
REPORT z0_02.
DATA:gt_itab TYPE STANDARD TABLE OF sflight,gs_wa LIKE LINE OF gt_itab.
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_itabFROM sflight.
IF sy-subrc EQ 0.
LOOP AT gt_itab INTO gs_wa.
WRITE: / gs_wa-carrid, gs_wa-connid.
ENDLOOP.
ENDIF.
gt_itab
是保存SELECT
语句结果值的内表。
gs_line
是72位CHAR类型。gs_line
变量里写出字段名,查询SFLIGHT
表的字段carrid
connid
值输出到画面上。如果需要72位以上时,定义72位内表的内表使用即可,详细请参照[例3] 。
REPORT z0_03.-----中间省略---
DATA gs_line(72) TYPE c.
DATA gt_list LIKE TABLE OF gs_line(72).
gs_line = 'CARRID CONNID'.
APPEND gs_line TO gt_list.
SELECT DISTINCT (gt_list) INTO TABLE gt_itabFROM sflight.
-----中间省略-----
2.2 INTO语句
用此语句指定存储SELECT语句查询的结果值的目的地。
- 结构体
当查询一条数据时使用结构体(Work Area,变量,结构体),使用星号*能取得所有字段的值。此时使用CORRESPONDING FIELDS OF
语句会自动找到相同字段名匹配赋值。
SELECT … INTO [CORRESPONDING FIELDS OF]。
- 内表(Internal Table)
当查询多条数据时使用内表。往内表插入数据时使用APPENDING
,不能使用INTO
,INTO
是删除内表数据后插入数据时使用的。
SELECT …INTO|APPENDING [CORRESPONDING FIELDS OF]
TABLE
[PACKAGE SIZE]…
用PACKAGE SIZE
语句可以指定每次追加到内表里的数据件数。当PACKAGE SIZE
设置为5时,则每次只读取5条数据添加到内表中,此时要注意,需要使用ENDSELECT
语句。
REPORT z0_04.
DATA:gs _wa TYPE sflight,
gt_itab TYPE TABLE OF sflight.
SELECT carrid connid
FROM spfli
INTO CORRESPONDING FIELDS OF TABLE gt_itab PACKAGE SIZE 5.
LOOP AT gt_itab INTO gs_wa.
WRITE:/ gs_wa-carrid, gs_wa-connid.
ENDLOOP.
ENDSELECT.
由于PACKAGE SIZE
指定为5,因此SELECT
语句每次只读取5条值执行LOOP
循环后再重新执行SELECT
语句。[例3-4]中的内表gt_itab
参照了数据库表sflight
,而FROM
语句参照了数据库表spfli
。这两个表是两个不同的结构,因此使用了CORRESPONDING FIELDS OF
选项使两个表找到相同字段进行赋值。
- Single Field
查询数据库表的个别字段或者使用Aggregate函数时使用如下所示的语句。
INTO语句后面列出两个以上目标地时需要用括号分别指定变量名。若存在空白,则会发生语法错误。
SELECT … INTO (f1.f2… …)
在SELECT语句里查询两个字段的语句如下所示。
SELECT carrid connid INTO (gv_carrid, gv_connid) FROM SFLIGHT.
2.3 FROM语句
用FROM
语句指定要查询数据的相应数据库表(或者视图)。FROM
语句后面可以指定一个数据库表或者多个数据库表的连接。不仅可以使用AS 语句添加别名,还可以动态地定义数据库表名。
FROM
语句有两个选项,一个是定义表的选项,另一个是控制访问数据库表的选项。
用FROM
语句指定要查询数据的相应数据库表(或者视图)。FROM
语句后面可以指定一个数据库表或者多个数据库表的连接。不仅可以使用AS 语句添加别名,还可以动态地定义数据库表名。FROM
语句有两个选项,一个是定义表的选项,另一个是控制访问数据库表的选项。
SELECT … FROM table option .
在FROM语句中控制访问数据库表的选项语法如表3-3所示。
表3-3 FROM语句的选项
语句 | 说明 |
---|---|
CLIENT SPECIFIED | 解除自动client设置 |
BYPASSING BUFFER | 不会从SAP本地缓冲器中读取数据。即使数据库表中设置了 Buffering 也会直接访问数据库读取数据 |
UP TO n ROws | 限制查询数据的个数。可以预防由于用户使用问题而导致的降低数据库性能问题。例如,由于在选择条件中没有指定日期而导致查询大批量数据的情况 |
- 选择静态表
可以定义静态表查询数据。这时可以使用别名,但是表名不能在SELECT语句中使用。
SELECT … FROM [AS]
- 选择动态表
可以定义动态表查询数据。这时表名一定要用大写字母指定并且必须是ABAP数据字典中存在的名字。
SELECT … FROM (dbtab).
从画面上用户输入的数据库表中查询数据的语句如[例5]所示。
REPORT Z0_05.
PARAMETERS p_tname TYPE char10.DATA GS_WA TYPE SFLIGHT.
SELECT SINGLE* INTO gs_waFROM (p_tname)
WHERE carrid ='AA'.
执行[例3-5]会显示如[结果 3-5]所示的选择画面,在此画面上用户可以输入要查询数据的数据库表名,用PARAMETERS
语句会自动生成此画面。在此画面上,输入数据库表名SFLIGHT
后单击执行按钮,则在FROM(p_tname)
语句中使用的变量p_tname
中,会动态地赋上用户输入的数据库表名SFLIGHT
。
**JOIN**
语句
在关系数据库中同时取得多个数据库表值时使用JOIN 语句连接表。一般使用Primary Key
(此后用缩写PK来替代)和Foreign Key
(此后用缩写FK来替代)来连接数据库表,但是偶尔也会用符合逻辑的相关值进行连接,用ON语句指定两个表连接条件。
SELECT …FROM [INNER] JOIN [AS ]
ON …
[例6]是说明INNER JOIN
语句的实例。可以发现,存储航空信息的数据库表SFLIGHT
中不存在航空公司名字,但是数据库表SCARR
中存在航空公司ID所对应的航空公司名字。因此用JOIN
语句连接这两个表就可以读取航空公司的名字。
使用JOIN
语句时若不指定JOIN
类型,则默认为是 INNER JOIN
。
REPORT z0_06.
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_strFROM sflight AS a
INNER JOIN scarr AS bON a-carrid EQ b-carridWHERE a~carrid ='AA'.
WRITE : gs_str-carrid, gs_str-carrname.
[结果3-6]
AA American Airlines
[例3-6]中的JOIN语句中AS语句用于指定别名即 sflight AS a语句中a作为数据库表sflight别名使用。使用别名能简化程序代码,从[例3-6]中可以看出,sflight-carrid语句可以用a~carrid 语句替代。
I**NNER JOIN**
与**OUTERJOIN**
数据库表连接类型有INNER JOIN
与OUTER JOIN
这两种。其中OUTER JOIN
的方法如下所示。
SELECT…FROMLEFT [OUTER] JOIN
[AS ]
ON
假设有如[图7]所示的两个人事信息数据库表。数据库表INSA存储员工基本信息,数据库表CERT存储员工取得的证书信息。员工ZHOU与KIM有证书,而员工ZHONG却没有证书。当以员工编号字段为基准执行INNER JON,则从查询对象中应该排除员工ZHONG。
假设要显示所有员工的基本信息并且还要追加显示证书信息时要使用OUTER JOIN
。在ABAP OPEN SQL
中只能使用LEFT OUTER JOIN
。此语句是将左边的表作为基准表读取数据。其连接结果如图3-8所示。
[例7]说明OUTER JOIN
的方法。假设数据库表SCARR
中所有航空公司的名字都不存在,因此航空公司为了避免遗漏航空公司的航空器信息要LEFT OUTER JOIN
数据库表SFLIGHT
与数据库表 SCARR
。
REPORT Z0_07.
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 OUTER JOIN scarr AS b ON a~carrid EQ b~carrid
WHERE a~carrid = 'AA'.
WRITE: gs str-carrid, gs str-carrname.
- 限制查询个数
利用下列语句可以限制要查询的数据个数。
SELECT …FROM UP TO ROWs…
此语句相当于[图3-9]的程序查询条件SELECTIOIN SCREEN
中的最大取得数。当用户不输入查询条件而直接执行程序时会查询数据库表中的所有值,这样会增加系统负荷。此时可以指定最大取得数而限制取得数据的个数。
2.4WHERE语句
WHERE
语句可以指定查询条件使用户正确地取得自己所需数据,此语句还适用于UPDATE
、DELETE
等命令。
- WHERE条件语句
SELECT …WHERE …
[表4]说明在WHERE语句中使用的运算符类型。
- Interval条件
需要在条件中追加范围值时使用此语句。
SELECT… WHERE
[NOT ] BETWEEN <f 1> AND <f 2>
例如,取得字段COL为1~10的数据时可以写成WHERE COL BETWEEN 1 AND 10。
- 字符串比较
比较字符串时使用LIKE语句。若要取得以ABC开头的数据,则可以追加如下条件。
COL2='ABCDEFGHIGJ".
SELECT~ WHERE COL2 LIKE ‘ABC%’.
若要取得以ABC 开头的4位长字符串时,例如,在ABCD、ABCE、AFCF、ABCG等数据中只比较一位时可以使用符号’_'。
WHERE COL2 LIKE 'ABC_ ’
- LIST VALUE
利用IN语句可以取得符合多种情况的数据。例如,读取居住在’北京’、'上海’的人时条件可以为“WHERE地址 IN(‘北京’,‘上海’")”。
SELECT…WHERE
[NOT] IN(<f 1>, …,) …
- SELECTION TABLE
利用IN语句可以查询存储在Selection Table,Range变量里的数据。Selection Table, Range变量类似于内表,可以存储多条数据。
SELECT… WHERE
[NOT ] IN …
- 动态条件
可以动态地写SELECT语句的 WHERE条件。下列语句中的 itab可以定义成最大为72位的内表。
SELECT… WHERE () …
参照[例8]、[例9]学习动态给出查询条件的程序。
*[例8]
REPORT z0_08.
DATA gs _where TYPE c LENGTH 72.DATA gv_carrname TYPE scarr-carrname.
DATA gv_carrid TYPE scarr-carrid VALUE'AC".
CONCATENATE 'CARRID=''' gv_carrid'''' INTO gs_where.
SELECT SINGLE carrname
INTO gv_carrname
FROM scarr
WHERE (gs_where).
WRITE / gv carrname.
[结果8]
Air Canada
[例3-8]是在数据库表SCARR中读取字段值CARRID等于AC的 SELECT语句,在这里动态地给出了WHERE条件。当需要给出两个以上查询条件时要把查询条件追加到内表中使用,如[例 3-9]所示。
[例9]
*[例9]
REPORT z03_09.
DATA gs _whereTYPE c LENGTH 72.
DATA gt_where LIKE TABLE OF gs _where.DATA gv_carrname TYPE scarr-carrname.
DATA gv_carrid1 TYPE scarr-carrid VALUE'AC'.
DATA gv_carrid2TYPE scarr-carrid VALUE'AF".
CONCATENATE 'CARRID=''' gv_carrid1'''' INTO gs_where.
APPEND gs _where TO gt_where.
gs _where = 'OR'.
APPEND gs _where TO gt_where.
CONCATENATE 'CARRID =''' gv_carrid2'''' INTO gs_where.
APPEND gs _where TO gt_where.
SELECT carrname
INTO gv_carrname FROM scarr
WHERE (gt_where).
WRITE / gv_ carrname.ENDSELECT.
[结果9]
Air Canada
Air France
- FOR ALL ENTRIES语句
SELECT…FOR ALL ENTRIES IN WHERE
FOR ALL ENTRY
语句与嵌套SELECT语句或Subquery 的功能相似。
使用FOR ALL ENTRY
语句时,WHERE语句中使用的条件必须是itab中存在的字段。
注意
- itab的字段要与比较对象的表字段类型一致。
-不能使用类似LIKE、BETWEEN、IN等比较语句。- itab中自动挪除重复数据(Unique Key 为基准).- itab为空则取得所有数据。
- itab中数据多时会增加LOOP循环次数,因此会降低选择速度。
例如itab
中数据为3条,则会执行3次“SELECT ~ ENDSELECT”
。
[例10]是先查询存储航班时刻表的数据库表spfli
的所有数据后用FOR ALL ENTRIES
语句从日期别航班运行信息数据库表中查询相关数据的程序。
*[例10]
REPORT z03_10.
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.
wWRITE: / gs _sflight-carrid, gs_sflight-connid.
ENDLOOP.
2.5 GROUPING语句
使用Aggregate
函数之前,选择数据时需要用GROUP BY
语句进行分组。GROUP BY
语句是当表的特定字段中存在相同值时其值就显示在一行中。
SELECT…
GROUP BY …
GROUP BY
语句后使用的字段一定要在SELECT语句中查询出来。
在SELECT
语句中可以使用字段及函数。
Aggregate
函数请参照[表5]。
也可以动态地指定GROUP BY
语句。
GROUP BY(itab)…
下面练习一下分别取得每个航班ID的平均预约占有率。[例11]
REPORT z0_11.
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.
[结果3-11]
AA 0017 136,905
AA 0064 90,139
AZ 0555 33,741
AZ 0788 320,638
在OPEN SQL
中利用SUM
函数时使用NTO CORRESPONDING FIELDS OFTABLE
语句会取不到预期的结果。
此时要利用AS语句为合计的字段起个别名,具体使用方法如下面代码所示。
SELECT CARRID
SUM( PRICE ) AS PRICEFROM SFLIGHT
INTO CORRESPONDING FIELDS OF TABLE GT_GLT WHERE CARRID = ‘AA’.
2.6 GROUPING
条件语句——HAVING
HAVING
是用GROUP BY
语句分组查询数据时使用的条件语句。类似于WHERE条件语句可以动态地定义其条件。
SELECT-…
GROUP BY<f 2>HAVING .
要取得[例11]中的平均占有率大于100,000件的数据时实现方法如下所示。
SELECT carrid connid AVG( paymentsum )
INTO (gv_carrid, gv_connid,gv_paymentsum) FROM sflight
GROUP BY carrid connid
HAVING AVG( paymentsum ) > 100000.
2.7 SORT语句
在查询数据时使用ORDER BY
语句,则查询出来的结果会按照ORDER BY
指定的字段进行排序。若不使用ORDER BY就会任意地显示排序结果。
ORDER BY PRIMARY KEY
–根据表的KEY值进行排序。-只适用于SELECT*语句。
-在JOIN语句和视图中无法使用。
SELECT *
ORDER BY PRIMARY KEY.
ORDER BY中可以使用所有字段。用ASCENDING,DESCENDING语句可以指定排序类型,如升,降序。
SELECT…ORDER BY[ASCENDING|DESCENDING]<2>IASCENDING|DESCENDINGl …
也可以动态地定义ORDER BY语句。使用的内表类型应为char且长度不能超过72位。
SELECT …ORDER BY (itab)
通过[例12]练习做一个以预约座位为基准升序排序的程序。
[例12]
*[例12]
REPORT Z03_12.
DATA:gv_carrid
TYPE sflight-carrid,
gv_connid
TYPE sflight-connid,
gY_paymentsum TYPE i.
SELECT carrid connid AVG( paymentsum ) as paymentsum
INTO (gv_carrid, gv_connid,gv_paymentsum)
FROM sflight
GROUP BY carrid connid
ORDER BY paymentsum.
WRITE:/ gv_carrid, gv_connid,gv_paymentsum.
ENDSELECT.
[结果12]
Az 0555 33,741
LH 2407 38,371
LH 2402 79,572
DL1699 80,025
由于在ORDER BY
语句中无法使用AVG(paymentsum)
等Aggregate
函数,因此查询数据时要用AS语句起别名“paymentsum”
。
2.8 子查询
子查询在 SELECT
语句中嵌套SELECT
语句时使用。
1.Scalar Subquery
利用子查询可以在 WHERE
语句中追加特殊条件。Subquery
的SELECT
语句中只能指定一个字段。
Scalar Subquery的定义
Scalar Subquery是指SELECT语句里面嵌套使用的SELECT语句.
返回一列值中的一个字段值(或者Aggregate
函数执行结果值),因此执行结果与JOIN语句相似。
Scalar subquery的理解
- Scalar subquery只能返回一个字段值。
- Scalar subquery以嵌套循环方式执行。
- Scalar subquery执行的次数是row数。
- 当查询重复的编号及主数据表时使用此语句就可以大大提高效率.下面通过[例3-13]学习Scalar Subquery的使用方法。
*「例13]
REPORT z03_13.
DATA:gv_carridTYPE sflight-carrid,
gv_connidTYPE sflight-connid,
gV_pay mentsun TYPE sflight-paymentsum.
SELECT SINGLE carrid connid paymentsumINTO(gv_carrid , gv_connid, gv_paymentsum)FROM sflight AS a
WHERE carrid IN ( SELECT carrid
FROM spfli
WHEREcarid = a-carridAND connid= a-connid )AND a-carrid = 'AA'.
WRITE: gv_carrid, gv_connid, gv paymentsum.
2.Non-scalar Subquery
当存在Subquery查询的数据时返回TRUE,不存在时返回FALSE。
使用 EXISTS语句实现,具体方法请参照[例3-14]。
[例14]
*[例14]
REPORT Z03_14.
DATA:gv_carrid TYPE sflight-carrid,
gv_connid TYPE sflight-connid,
gv_paymentsum TYPE sflight-paymentsum.
SELECT SINGLE carrid connid paymentsumINTO (gv_carrid , gv_connid,gv_paymentsum)
FROM sflight AS a
WHERE EXISTS ( SELECT*FROM spfli
wWHERE carrid = a-carridAND connid= a-connid ,AND a-carrid = 'AA'.
WRITE:gv_carrid,gv_connid,gv_paymentsum.