[SAP ABAP开发技术总结]OPEN SQL

[SAP ABAP开发技术总结]OPEN SQL
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4264698.html

OPEN SQL也是ABAP开发人员必备的知识,虽然可以使用原生的SQL来写,但不建议,就像JDBC与Hibernate的关系,性能与跨数据库的选择。但为了开发的简便与可移值性,还是使用Open
SQL吧!这里贴出一些常用的操作,做项目时我也经常翻出来看一眼再写。

4.

OPEN SQL

.

43

4.1.

SELECT

INSERT

UPDATE

DELETE

MODIFY

.

43

4.2.

条件操作符

...

44

4.3.

RANG

条件内表

...

44

4.4.

FOR ALL ENTRIES

.

45

4.5.

INNER JOIN

LEFT OUTER JOIN

使用限制

...

46

4.6.

动态

SQL

.

46

4.7.

子查询

...

47

4.7.1.

=

<>

<

<=

>

>=

子查询

...

47

4.7.1.1.

ALL

ANY

SOME

.

48

4.7.2.

[NOT] IN

子查询

...

48

4.7.3.

[NOT] EXISTS

子查询

...

48

4.7.4.

相关子查询

...

48

4.8.

统计函数

...

48

4.9.

分组过滤

...

48

4.10.

游标

...

49

4.11.

三种缓存

...

49

4.12.

Native SQL

.

50

4.12.1.

查询

...

50

4.12.2.

存储过程

...

50

4.12.3.

游标

...

50

4.13.

SAP

...

51

4.

OPEN SQL

4.1.

SELECT

INSERT

UPDATE

DELETE

MODIFY

如果从数据库读出来的数据存在重复时

不能存储到

Unique

内表中去

——

Unique

的排序表与哈希表


SELECT




SINGLE


...


INTO



[

CORRESPONDING

FIELDS OF

] wa

WHERE

...

SELECT SINGLE

<cols>

...

INTO

(

dobj1

,

dobj2

,

...

)

WHERE

...

SELECT

...

FROM

<tables>

UP TO

<n>

ROWS

...


SELECT


...


INTO


|

APPENDING

CORRESPONDING

FIELDS OF


TABLE


<itab>

...

单条插入

:在插入时是按照数据库表结构来解析

<wa>

结构,与

<wa>

中的字段名无关,所以

<wa>

的长度只少要等于或大于所对应表结构总长度

INSERT

INTO

<tabname>

VALUES

<wa>


INSERT


<tabname>



FROM


<wa>

多条插入

itab

内表的行结构也必须和数据库表的行结构一致;

ACCEPTING DUPLICATE KEYS

:如果现出关键字相同条目,系统将

SY-SUBRC

返回

4

,并跳过该条目,但其他数据会插入进去


INSERT


<tabname>


FROM




TABLE

<
itab
>

[

ACCEPTING DUPLICATE KEYS

]

单条更新:

会根据数据库表关键字来更新其他非关键字段。如果

WA

工作区是自己定义的且未参照数据库表,则

WA

的结构需要与数据库表相一致,且不能短于数据库表结构,但字段名可任意取

UPDATE

dbtab

FROM

wa

多条更新:

主键不会被更新,即使在

SET

后面指定后也不会被更改


UPDATE


dbtab


SET

f1 = g1 … fi = gi


WHERE

<conditions>

UPDATE

dbtab

FROM

TABLE

itab

与从

WA

工作区单条更新原理一样,根据数据表库关键字段来更新,且行结构要与数据库表结构一致,并且不能短于数据库表结构,一样内表行结构组件名可任意

单条删除:

下面的

WA

Itab

原理与

Update

是一样的

DELETE

dbtab

FROM

wa

多条删除:

DELETE

dbtab

FROM

TABLE

itab


DELETE



FROM



dbtab



WHERE


<conditions>

插入或更新:

下面的

WA

Itab

原理与

Update

是一样的

MODIFY

dbtab

FROM

wa

单行


MODIFY


dbtab



FROM




TABLE



itab

多行,有就修改,没有就插入

4.2.

条件操作符

=

<>

<

<=

>

>=

[

NOT

]

BETWEEN

...

AND

[

NOT

]

LIKE

[

NOT

]

IN

IS

[

NOT

]

NULL

4.3.

RANG

条件内表

两种定义方式:

RANGES

seltab


FOR


dobj [

OCCURS

n].

其中

dobj

自定义变量

或者是参照某个

表字段

SELECT-OPTIONS

selcrit

FOR


{dobj|(name)}

上面两个语句会生成如下结构的内表,该条件内表的每一行都代表一个逻辑条件

DATA

:

BEGIN

OF

seltab

OCCURS

0

,

        sign

TYPE

c

LENGTH

1

,

允许值为

I

E

I

表示包含

Include

E

表示排除

Exclude

option

TYPE

c

LENGTH

2

,

OPTION

表示选择运算符

low

LIKE


dobj

,

下界

,相当于

前面文本框

中的值

high

LIKE


dobj

,

上界

,相当于

后面文本框中的值

END

OF

rtab.

option

: HIGH

字段为空,则取值可以为:

EQ

=

)、

NE

<>

)、

GT

>

)、

GE

>=

)、

LE

<=

)、

LT

<

)、

CP

NP

CP

(集合之内的数据)和

NP

(集合之外数据)只有当在输入字段中使用了通配符(“

*

”或“

+

”)时它们才是有效的

SELECT

...

WHERE

...

field

[NOT]

IN

seltab

...

如果

RANG

条件内表为空

IN
seltab

逻辑表达试恒为真

XX NOT IN

seltab

恒为假

注:

不会像

FOR ALL ENTRIES

那样

忽略其他的条件表达式

其他条件还是起作用

4.4.

FOR ALL ENTRIES

1、

使用该选项后,对于最后得出的结果集系统

会自动删除重复行


。因此如果你要保留重复行记录时,记得在

SELECT

语句中添加足够字段

2、

FOR ALL ENTRIES IN

后面使用的内部表

itab

如果

为空

,将查出

当前

CLIENT



所有数据(

即忽略整个

WHERE

语句

,其他条件都会被忽略)

3、

内表中的条件字段

不能使用
BETWEEN

LIKE


IN


比较操作符

4、

使用该语句时,

ORDER BY

语句和

HAVING


语句

不能使用

5、

使用该语句时,


COUNT

( * )

(并且如果有了

COUNT

函数,则不能再选择其他字段,只能使用在

Select ... ENDSelect

语句中了)以外的

所有合计函数(

MAX,MIN,AVG,SUM

)都不能使用

即使

Where

后面还有其它条件,所有的条件都会忽略

SELECT

vbeln posnr pstyv werks matnr arktx lgort waerk kwmeng

FROM

vbap

INTO TABLE

gt_so

FOR ALL

ENTRIES

IN

lt_matnr

WHERE

matnr

=

lt_matnr

-

matnr

AND

vbeln

IN

s_vbeln

AND

posnr

IN

s_posnr

.

如果上面的

lt_matnr

为空,则“

AND  vbeln IN s_vbeln AND posnr IN s_posnr

”条件也会忽略掉,即整个

Where

都会被忽略掉。

SELECT

matnr

FROM

mara

INTO

CORRESPONDING

FIELDS OF TABLE

strc

FOR ALL

ENTRIES

IN

strc

WHERE

matnr

=

strc

-

matnr

.

生成的

SQL

语句:

SELECT

"MATNR"

FROM

"MARA"

WHERE

"MANDT" = '210' AND "MATNR" IN ( '000000000000000101' , '000000000000000103'
, '000000000000000104' )

:这里看上去

FOR ALL ENTRIES

使用

IN

表达式来代替了,这是只有使用到内表中一个条件是这样的,如果使用多个条件时,不会使用

In

表达式,而是使用

OR

连接,像这样:

[SAP ABAP开发技术总结]OPEN SQL

[SAP ABAP开发技术总结]OPEN SQL

另外,在使用

FOR ALL ENTRIES

时,不管使用了条件内表中的一个还是多个条件字段,都会以

5


值为单位进行

SQL

发送

4.5.

INNER JOIN

LEFT OUTER JOIN

使用限制

ON

后面的条件与

Where

条件类似,但有以下不同:

2

必需有

ON

条件语句,且多个条件之间只能使用

AND

连接

2

每个条件表达式中

两个操作数之中必须有一个字段是来自于

JOIN

右表

2

如果是

LEFT OUTER JOIN

,则

至少有一个条件表达式的两个操作数一个是来自于左表,另一个来自右表

2

不能使用

NOT

LIKE


IN

(但如果是

INNER JOIN

,则

>


<


BETWEEN …AND


<>

都可用)

2

如果是

LEFT OUTER JOIN

,则只能使用等号操作符:

(

=

EQ

)

2

如果是

LEFT OUTER JOIN


同一右表不能多次出现在不同的

LEFT OUTER JOIN

ON

条件表达式中

2

LEFT OUTER JOIN

的右表所有字段不能出现在

WHERE

2

如果是

LEFT OUTER JOIN

,则在同一个

ON

条件语句中

只能与同一个左表进行关联

4.6.

动态

SQL

SELECT

(

column_syntax

)

FROM

...

column

:可以是内表,也可以是字符串

TYPES

:

line_type

TYPE c

LENGTH

72

.

DATA

:

column_syntax

TYPE TABLE OF

line_type

.

APPEND

'CARRID'

TO

column_syntax

.

APPEND

'CITYFROM CITYTO'

TO

column_syntax

.

SELECT

...

FROM

(dbtab_syntax)...

PARAMETERS

:

p_cityfr

TYPE

spfli

-

cityfrom

,

p_cityto

TYPE

spfli

-

cityto

.

DATA

:

BEGIN OF

wa

,

fldate

TYPE

sflight

-

fldate

,

carrname

TYPE

scarr

-

carrname

,

connid

TYPE

spfli

-

connid

,

END OF

wa

.

DATA

itab

LIKE SORTED TABLE OF

wa

WITH UNIQUE KEY

fldate carrname connid

.

DATA

:

column_syntax

TYPE

string

,

dbtab_syntax

TYPE

string

.

column_syntax

=

`c~carrname p~connid f~fldate`

.

dbtab_syntax

=

`( ( scarr AS c `

&

` INNER JOIN spfli AS p ON p~carrid  = c~carrid`

&

` AND p~cityfrom =

p_cityfr

`

&

` AND p~cityto   =

p_cityto

)`

&

` INNER JOIN sflight AS f ON f~carrid = p~carrid `

&

` AND f~connid = p~connid )`

.

SELECT

(

column_syntax

)

FROM

(

dbtab_syntax

)

INTO CORRESPONDING

FIELDS OF TABLE

itab

.

SELECT

...

WHERE

(

cond_syntax

) ...

SELECT

...

WHERE

<cond>

AND/OR

(

cond_syntax

) ...

DATA

:

cond

(

72

)

TYPE c

,

itab

LIKE TABLE OF

cond

.

APPEND

'cityfrom = ''NEW YORK'''

TO

itab

.

APPEND

'or cityfrom = ''SAN FRANCISCO'''

TO

itab

.

SELECT

*

INTO TABLE

itab_spfli

FROM

spfli

WHERE

(

itab

)

.

DATA

:

cond1

(

72

)

TYPE c VALUE

'cityfrom = ''NEW YORK'''

,

cond2

(

72

)

TYPE c VALUE

'cityfrom = ''SAN FRANCISCO'''

.

SELECT

*

INTO TABLE

itab_spfli

FROM

spfli

WHERE

(cond1)

OR

(cond2)

.

DATA

:

cond

(

72

)

TYPE c

,

cond1

(

72

)

TYPE c VALUE

'cityfrom = ''NEW YORK'''

,

itab

LIKE TABLE OF

cond

.

APPEND

'cityfrom = ''SAN FRANCISCO'''

TO

itab

.

SELECT

*

INTO TABLE

itab_spfli

FROM

spfli

WHERE

(itab)

OR

(cond1)

.

DATA

:

cond

(

72

)

TYPE c

,

itab

LIKE TABLE OF

cond

.

APPEND

'cityfrom = ''SAN FRANCISCO'''

TO

itab

.

SELECT

*

INTO TABLE

itab_spfli

FROM

spfli

WHERE

(itab)

OR

cityfrom

=

'NEW YORK'

4.7.

子查询

colum

operator

[ALL|ANY|SOME]

[NOT]

EXISTS

[NOT]

IN

连接至

WHERE

从句与

HAVING

从句中

4.7.1.

=

<>

<

<=

>

>=

子查询

子查询的

SELECT


只有

一个表字段

或者是

一个统计列

,并且

只能返回一条数据

SELECT

*

FROM

sflight

INTO

wa_sflight

WHERE

seatsocc

=

(

SELECT

MAX

( seatsocc )

FROM

sflight ).

ENDSELECT

.

操作符可以是:

=


<>



<



<=



>


>=

4.7.1.1.

ALL

ANY

SOME

如果子查询

返回的是多条

,则使用

ALL

ANY

SOME

来修饰

SELECT

customid

COUNT

( * )

FROM

sbook

INTO

(id, cnt)

GROUP

BY

customid

HAVING

COUNT

( * )

>=

ALL

(

SELECT

COUNT

( * )

FROM

sbook

GROUP

BY

customid ).

ENDSELECT

.

2

ALL

:主查询数据大于

所有


子查询返回的行数据时,才为真

2

ANY|SOME

:主查询数据只要大于

任何


一条子查询返回的行数据时,才为真

2

= ANY|SOME

:等效

IN

子查询

4.7.2.

[NOT] IN

子查询

此类子查询

SELECT

中也只有单独的

一列

选择列,但查询出的

结果可能有多条

SELECT

SINGLE

city latitude longitude

INTO

(city, lati, longi)

FROM

sgeocity

WHERE

city

IN

(

SELECT

cityfrom

FROM

spfli

WHERE

carrid = carr_id

AND

connid = conn_id ).

4.7.3.

[NOT] EXISTS

子查询

这类

子查询没有返回值

,也

不要求

SELECT


从句中只有一个选择列

,选择列可以任意个数,

WHERE

或者

HAVING

从句根据该子查询的是否查询到数据来决定外层主查询语句来选择相应数据

SELECT

carrname

INTO

TABLE

name_tab

FROM

scarr

WHERE

EXISTS

(

SELECT

*

FROM

spfli

WHERE

carrid =


scarr~carrid

AND

cityfrom =

'NEW YORK'

).

4.7.4.

相关子查询

上面的示例子查询即为

相关子查询

如果某个子查的

WHERE

条件中引用了外层查询语句的列,则称此子查询为相关子查询。相关子查询对外层查询结果集中的每条记录都会执行一次,所以尽量少用相关子查询

4.8.

统计函数

MAX

MIN

AVG

SUM

COUNT

,聚合函数都可以加上

DISTINCT

选项

4.9.

分组过滤

如果将统计函数与

GROUP BY

子句一起使用,那么

Select


语句中未出现在统计函数的数据库字段都必须在


GROUP BY


子句中出现

。如果使用

INTO CORRESPONDING FIELDS

项,则需要在

Select

语句中通过

AS

后面的别名将统计结果存放到与之相应同名的内表字段中:

SELECT MIN

(

price

)

AS

m

INTO

price

FROM

sflight

GROUP BY

carrid

HAVING

MAX(

price

)

>

10

.

Having

从句中比较统计结果时,需要将统计函数重写一遍,而不能使用

Select

中定义的别名

ENDSELECT

.

4.10.

游标

DATA

:

c

TYPE

cursor

.

[?k?:s?]

DATA

: wa

TYPE

spfli.

"


1

打开游标

OPEN CURSOR

:

c

FOR

SELECT

carrid connid

FROM

spfli

WHERE

carrid =

'LH'

.

DO

.

"

2

、读取数据

FETCH NEXT CURSOR

c

INTO

CORRESPONDING

FIELDS

OF

wa.

IF

sy-subrc <>

0

.

"

3

、关闭游标

CLOSE

CURSOR

c

.

EXIT

.

ELSE

.

WRITE

: / wa-carrid, wa-connid.

ENDIF

.

ENDDO

.

4.11.

三种缓存

l

单记录缓存

:从数据库中仅读取一条数据并存储到

table buffer

中。此缓存只对

SELECT SINGLE…

语句起作用

l

部分缓存

:需要在指定

generic key

(即关键字段组合,根据哪些关键字段来缓存,可以是部分或全部关键字段)。

如果主键是由一个字段构成,则不能选择此类型缓存

。当你使用

generic key

进行数据访问时,则属于此条件范围的整片数据都会被加载到

table buffer

1

查询时如果使用

BYPASSING BUFFER

选项,除了绕过缓存直接到数据库查询外,查出的数据不会放入缓存

2

只要查询条件中出现了用作缓存区域的所有关键字段,则查询出所有满足条件全部数据进行缓存

3

如果查询条件中

generic key

只出现某个或者某部分,则不会进行缓存操作

4

如果主键是只由一个字段组成,则不能设定为此种缓存

5

如果有

MANDT

字段,则为

generic key

的第一个字段

[SAP ABAP开发技术总结]OPEN SQL

[SAP ABAP开发技术总结]OPEN SQL

l

全部缓存

:在第一次读取表数据时,会将整个表的数据都会缓存下来,不管

WHERE

条件

4.12.

Native SQL

4.12.1.

查询

DATA

:

BEGIN OF

wa

,

connid

TYPE

spfli

-

connid

,

cityfrom

TYPE

spfli

-

cityfrom

,

cityto

TYPE

spfli

-

cityto

,

END OF

wa

.

DATA

c1

TYPE

spfli

-

carrid

VALUE

'LH'

.

"

Native SQL

语句不能以句点号结尾

"

不能在

EXEC SQL…ENDEXEC

间有注释

,即不能有星号与双引号的出现;

"

参数占位符使用冒号,而不是问号;

EXEC SQL PERFORMING

loop_output

.

SELECT

connid

,

cityfrom

,

cityto

INTO


:


wa

"

或使用:

INTO :wa-connid ,:wa-cityfrom ,:wa-cityto

FROM

spfli

WHERE

carrid

=

:

c1

ENDEXEC.

FORM

loop_output

.

WRITE

:

/ wa

-

connid

,

wa

-

cityfrom

,

wa

-

cityto

.

ENDFORM

4.12.2.

存储过程

EXEC SQL.

EXECUTE PROCEDURE

proc1

(

IN

:

x,

OUT

:

y,

INOUT

:

z

)

ENDEXEC

.

4.12.3.

游标

DATA

:

arg1

TYPE

string

VALUE

'800'

.

TABLES

:

t001

.

EXEC SQL

.

OPEN

c1

FOR

SELECT

MANDT

,

BUKRS

FROM

T001

"

打开游标

WHERE

MANDT

= :

arg1

AND

BUKRS >=

'ZA01'

ENDEXEC

.

DO

.

EXEC SQL

.

FETCH NEXT

c1

INTO

:

t001

-

mandt

, :

t001

-

bukrs

"

读取游标

ENDEXEC

.

IF

sy

-

subrc <>

0

.

EXIT

.

ELSE

.

WRITE

:

/ t001

-

mandt

,

t001

-

bukrs

.

ENDIF

.

ENDDO

.

EXEC SQL

.

CLOSE

c1

"

关闭游标

ENDEXEC

.

4.13.

SAP

通用数据库表锁函数:

ENQUEUE_E_TABLE

DEQUEUE_E_TABLE

DEQUEUE_ALL

(解锁所有)

[kju:]

特定数据库表锁函数:

EN
QUEUE

_<LOCK OBJECT>

DENQUEUE

_<LOCK OBJECT>

自定义的锁对象都必须以

EZ_

或者

EY_

开头来命名

允许第二次加锁模式

第一次加锁模式

S

E

X

S

共享锁

否(

否(否)

E

可重入的排他锁

否(

否(

否(否)

X

排他锁

否(否)

否(否)

否(否)

括号内为同一程序(即同一事务内)内,括号外为非同一程序内

CALL FUNCTION

'ENQUEUE

_EZ_ZSPFLI'

"

加锁

EXPORTING

mode_zspfli

=

'E'

mandt

=

sy

-

mandt

   carrid

=

'AA'

connid

=

'0011'

*   X_CARRID            
= ' '"

设置字段初始值(

Initial Value

),若为

X

,则当遇到与

CARRID

的初始值

Initial Value

相同值时才会设置锁对象。

CARRID

的初始值只需在数据库表字段中选择

Initial Value

选项

(SE11

中设置

)

。当没有设置

X

时,则会用该锁函数所设置的

Default Value

指定初始值

*   X_CONNID            
= ' '

*   _SCOPE              
= '2'"

该选项只有在

UPDATE

函数(

CALL FUNCTION FM IN UPDATE TASK

)中才起作用,用来控制锁的传递。一般当调用解锁函数

DEQUEUE

或程序结束时(

LEAVE PROGRAM

或者

LEAVE TO TRANSACTION

)锁就会被自动解除,另外,遇到

A

X

消息时或用户在命令框中输入

/n

时锁也会被解除,但是,当事务码正在执行

UPDATE

函数时就不一样了,函数结束时是否自动解除锁则要看该选项

_SCOPE

了:

1-

表示程序内有效

2-

表示

update module

内有效

3-

全部

*   _WAIT               
= ' '"

表示如果对象已经被锁定

,

是否等待后再尝试加锁

*   _COLLECT            
= ' '"

参数表示是否收集后进行统一提交

程序锁定:

ENQUEUE_

ES_PROG

DEQUEUE_ES_PROG

上一篇:数据库优化系列——SQL性能优化十条建议


下一篇:[SAP ABAP开发技术总结]字符串处理函数、正则表达式