OPEN SQL

OPEN SQL

1.1 概要

R/3 体系结构

R/3 体系结构

  • SAP R/3 分为 表示层、应用层、数据库层。

  • 表示层

    就是个人PC(计算机),用于保存构成 SAP GUI 的软件组件,提供 R/3 系统与用户之间的接口。

    SAP GUI 相当于手机上的 APP ,用户可以通过此输入或者查询数据。

  • 应用层

    SAP 中所有程序都在应用层上执行。应用层上存在本地缓冲器,可以通过在数据字典中的数据表中设置缓冲器,访问数据库的请求都会直接在缓冲器中读取数据,用来提高 SAP 的性能,只适用于 OPEN SQL 。

  • 数据库层

    SAP 中所有数据都存储在本层,例如:画面、函数、数据库表、事务码以及 R/3 系统的所有数据。

    SAP 禁止一般用户直接连接数据库修改数据。

    ABAP 程序中使用的对象那个(数据表、视图、结构体、类型等)统称为 ABAP 数据字典。

1.2 SQL 定义

SQL 语言分为 三种 :

  • DML 用于查询、插入、删除、更新数据库 。
  • DDL 用于创建数据库。
  • DCL 保证数据完整性、安全性及权限控制。

ABAP 程序中 OPEN SQL 里只允许使用 DML 语言。

SQL 语言包含 OPEN SQL 和 NATIVE SQL 两种,OPEN SQL 只在 ABAP 程序中使用,通过数据库接口解析成 NATIVE SQL 后才能连接到数据库中。

在这里插入图片描述

1.2.1 OPEN SQL 和 NATIVE SQL

  • OPEN SQL

    由创建数据库数据的 ABAP 命令构成的,不能使用 DDL 、 DCL ,只能使用 DML 语言。而且还可以使用本地缓冲器。

  • NATIVE SQL

    可以直接连接数据库使用 DML 、DDL语言,无法使用 OPEN SQL 解决的问题可以通过 NATIVE SQL 解决。

1.2.2 SQL本地缓冲器

作用是减小数据库负荷。得在数据库表的设置里使用缓冲器。

OPEN SQL 依赖于客户(Client),R/3 系统是由多个独立的客户组成的,数据库表是依赖于客户独立存在的对象,一般表中都会存在 MANDT 字段,MANDT字段通常代表客户端(Client)。客户端是SAP系统中的一种数据隔离机制,允许在同一系统中存储多个不同的业务数据环境。每个客户端的数据相互独立,可以为不同的组织、部门、客户等提供服务,而不必担心数据之间的干扰。

  • MANDT是一个3位数的字段,表示客户端的唯一标识符(Client ID)。
  • 客户端是SAP系统中的一个数据分区,每个客户端具有自己的数据和设置。
  • 通过MANDT字段,SAP系统能够区分和存储不同客户端的数据。一个SAP系统通常可以配置多个客户端,在这些客户端中,业务数据是互不干扰的。
  • MANDT字段出现在大多数SAP数据库表中,作为区分不同客户端数据的标识。

假设SAP系统中有多个客户端:

​ 客户端 100:用于开发环境

​ 客户端 200:用于测试环境

​ 客户端 300:用于生产环境

每个客户端的数据将存储在相应的表中,并且通过MANDT字段加以区分。
总之,MANDT字段在SAP中用于标识和管理客户端,是多客户端环境下数据隔离和管理的关键。

OPEN SQL 命令语句:

关键字功能
SELECT从数据库中查询数据
INSERT往数据库中添加数据
UPDATE修改数据库表的数据
MODIFY具有 INSERT 和 UPDATE 两种功能,数据库中存在该数据时则修改数据,反之,则直接插入数据。
DELETE删除数据库表数据

1.3 OPEN SQL——SELECT

  • 读取数据库表中所有字段时使用星号(*)。
  1. SELECT

    表示查询数据的个数,SINGLE 代表只读取一条数据。

    表示要查询的字段。

    SELECT <lines> <columns> ...
    
  2. 读取一条数据

    使用 SINGLE 语句。只会取得一条数据,因此要正确的给出要查询数据的条件。即在 WHERE 条件里附带所有的 key 值。当没有指明所有 key 值时,就会返回多条数据中的任意一条。

    KEY值是由一组字段或字段组合构成的主键,用于唯一标识每一条记录。通过使用主键,SAP系统可以确保数据的一致性、唯一性和完整性。

    SELECT SINGLE <columns> WHERE ...
    
  3. DISTINCT 去重

SELECT DISTINCT <columns> WHERE ...

SELECT 语句中还有 ENDSELECT 语句,用于结束 SELECT 语句。

SELECT 语句的使用和 ENDSELECT 语句的必要性,取决于你查询数据的方式和你如何处理查询结果。

  • SELECT 单条数据
    如果你使用的是普通的 SELECT SINGLE 或者是 SELECT INTO,那么查询将只返回一个结果,不需要使用 ENDSELECT。
    例如:

    SELECT SINGLE * FROM mara WHERE matnr = '1000001'.
    

在这个例子中,SELECT SINGLE 只会返回一行数据,因此不需要 ENDSELECT。

  • SELECT 多条数据
    当你使用 SELECT … INTO TABLE 或者直接查询多条记录时,通常会使用循环 (LOOP) 结构来处理查询结果。在这种情况下,必须使用 ENDSELECT 来标识查询结束。
    例如:

    SELECT * FROM mara WHERE matnr LIKE '100%' INTO TABLE tableName.
    

    这里,数据会被查询并存储到内表 tableName 中,你通常会继续处理这些数据。如果你需要通过循环去逐行处理查询结果,可以结合 LOOP 和 ENDSELECT。

    SELECT * FROM mara WHERE matnr LIKE '100%' INTO TABLE tableName.
    
    LOOP AT result INTO lineName.
      WRITE: / lineName-matnr, lineName-werks.
    ENDLOOP.
    
    ENDSELECT.
    

    需要注意的是 INTO 语句可以写在 WHERE 之前,也可以写在之后。

  • ENDSELECT 的应用
    ENDSELECT 只在使用 SELECT 与 LOOP 结合时需要,或者在用 SELECT … INTO 时需要逐行处理每一条结果。ENDSELECT 是为了在读取每一行数据时结束查询结果的循环。
    **示例:**SELECT 多条数据与 ENDSELECT 结合
    假设你想查询并逐行处理一个表中的多个记录:

    DATA: lv_matnr TYPE mara-matnr.
    
    SELECT matnr FROM mara WHERE matnr LIKE '100%'.
    
      WRITE: / lv_matnr.
    
    ENDSELECT.
    

    在这个例子中,ENDSELECT 是必需的,它标志着查询结束并表示读取数据行的循环。

    总结:

    ​ 无需 ENDSELECT:当你使用 SELECT SINGLE 或 SELECT INTO 查询单条数据时,不需要 ENDSELECT。
    ​ 需要 ENDSELECT:当你在使用 SELECT 查询多条记录时,并且没有将结果直接存储到内表,而是需要逐条处理查询结果时,必须使用 ENDSELECT。

  1. AS(别名)

    类似于 MYSQL 一样,我们可以为字段或者数据库表设置别名。

    SELECT a.matnr AS Material a.werks AS Plant b.lifnr AS Supplier
            INTO (structure|table) 
          FROM mara AS a
          WHERE a.matnr = '1000001'.
    
  2. 动态 SELECT 语句

    可以动态的定义 SELECT 语句要查询的字段。保存动态语句的结构体最多可以容纳72位的 char 类型。当结构体为 null 时,与 * 意义相同。

    DATA: gt_itab TYPE STANDARD TABLE OF sflight,	
        '定义了一个与sflight结构相同的标准表gt_itab
        '表分为三类:标准表 排序表 哈希表 (之后会分析,可能不在本篇文章内)gs_wa
    	gs_wa LIKE LINE OF gt_itab.	'创建了一个变量gs_wa,与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_itab FROM sflight.
        
        IF sy-subrc EQ 0.	'sy-subrc = 0 说明 SELECT 语句执行成功
        	LOOP AT gt_itab INTO gs_wa.	'将gt_itab表中的每一行数据抽取出来赋值给 gs_wa
        		WRITE: / gswa-carrid , gs_wa-connid.	'从 gs_wa 中取相应字段的值 之间用 - 进行连接
        	ENDLOOP.
        ENDIF.
        
        '也可以这么写
        SELECT DISTINCT (gs_line) INTO TABLE gt_itab FROM sflight.
        
        IF sy-subrc EQ 0.	'sy-subrc = 0 说明 SELECT 语句执行成功
        	LOOP AT gt_itab INTO gs_wa.	'将gt_itab表中的每一行数据抽取出来赋值给 gs_wa
        		WRITE: / gswa-carrid , gs_wa-connid.	'从 gs_wa 中取相应字段的值 之间用 - 进行连接
        	ENDLOOP.
        ENDIF.
        ENDSELECT.
    
  3. INTO 语句

    指定将查询到值存储到目的地。

    • 结构体

      查询一条语句时使用结构体,使用星号取所有字段之后使用 CORRESPONDING FIELDS OF语句会自动找到相同字段名的值匹配赋值。

      SELECT * INTO CORRESPONDING FIELDS OF gs_sfl from sflight WHERE CONNID = '1001'.
      
    • 内表

      当查询多条数据时使用内表。

      往内表中插入数据有 APPENDING 和 INTO, APPENDING 是往内表中追加数据,而 INTO 是删除数据库表的数据后插入数据时使用的。

      SELECT ... INTO|APPENDING [CORRESPONDING FIELDS OF] TABLE <itab> [PACKAGE SIZE <n>]...
      

      使用PACKAGE SIZE可以指定添加到内表里的数据条数,注意要使用 ENDSELECT 语句。

      例:

      SELECT * 
      	INTO CORRESPONDING FIELDS OF TABLE ITAB
      	PACKAGE SIZE 5
      	FROM SPFLI
      ENDSELECT.
      
  4. 单条语句

    查询单条数据,添加进指定字段。可以如下写:

    SELECT ... INTO (f1,f2,f3...)
    '查询几个字段,INTO 后面就要跟几个字段,若存在空白,则会报语法错误。
    SELECT carrid connid INTO (gv_carrid,gv_connid) FROM SFLIGHT.
    
  5. FROM 语句

    指定要查询的数据库表或者视图。 该语句有两个选项,一个是定义表的选项,另一个是控制访问数据库表的选项。

    FROM 语句的选项

    语句说明
    CLIENT SPECIFIED解除自动 client 设置
    BYPASSING BUFFER不会从 SAP 本地缓冲器中读取数据,即使数据库中设置了 Buffering 也会直接访问数据库读取数据。
    UP TO n ROWS限制查询数据的个数,可以预防由于用户使用问题而导致的降低数据库性能的问题。例如:由于在选择条件中没有指定日期而导致查询大批量数据的情况。
    • 选择静态表

      定义静态表时可以指定别名,当指定了别名后,不能使用原来的表名了,只能使用别名。

    • 选择动态表

      SELECT ... FROM (dbtab)
      
      PARAMETERS p_tname TYPE char10.	
      'PARAMETERS 是用于声明 输入参数 的关键字。它通常用于在 选择屏幕(selection screen)中定义用户输入的字段,并为程序提供输入数据。定义的参数可以用于后续的处理逻辑中。
      '程序会在选择屏幕上生成一个输入框,让用户输入一个 10 字符长度的文本数据。用户输入的数据将被存储在变量 p_tname 中,并可以在程序中使用。
      DATA GS_WA TYPE SFLIGHT.
      
      SELECT SINGLE * 
          INTO gs_wa 
          FROM (p_tname) 
          WHERE carrid = 'AA'.
      
  6. JOIN 语句

    由 INNER JOIN 和 OUTER JOIN 两种。

    用 ON 指定两个表连接的条件。

    使用 INNER JOIN ON 连接条件左右表的字段都不为 null 时,才会查出数据。

    而使用 LEFT OUTER JOIN ON 时,一定会显示完整的左表数据,如果右表没有相应的值,则会显示 null 值。

    SELECT ... FROM <tab> [INNER] JOIN <dbtab> ON <option> WHERE ...
    
    SELECT ... FROM <tab> LEFT OUTER JOIN <dbtab> ON <option> WHERE ...
    

    OPEN SQL 中只能使用 LEFT OUTER JOIN ON

  7. 限制查询个数

    SELECT ... FROM <tab> UP TO <n> ROWS...
    
  8. WHERE 语句

    SELECT ... WHERE ...
    

    WHERE 中使用的运算符类型

    运算符意义运算符意义
    EQ等于LE小于或等于
    =等于<=小于或等于
    NE不等于GT大于
    <>不等于>大于
    ><不等于GE大于或等于
    LT小于>=大于或等于
    <小于
    • BETWEEN … AND …

      取得范围内的数据

    • LIKE 模糊匹配

      ( _ ) 表示任意一个字符,( % )表示多个任意字符

      在 WHERE 中使用 LIKE 关键字 ,之后使用单引号引起来。

    • IN

      获取符合条件的多种情况。

    • 动态条件

      DATA gs_where TYPE c LENGTH 72.
      gs_where = 'slight'.
      SELECT * 
      	INTO gv_carrname 
      	FROM scarr 
      	WHERE (gs_where). 
      
  9. FOR ALL ENTRIES IN

    • internal_table 中的字段要与比较对象的表字段类型一致。

    • internal_table 中自动删除重复数据。

    • internal_table 为空则会取到所有的数据。

    • internal_table 中数据多少会增加 LOOP 循环次数。

    SELECT <field_list>
      FROM <database_table>
      INTO <target_table>
      FOR ALL ENTRIES IN <internal_table>
      WHERE <database_table_field> = <internal_table_field>.
    
  10. GROUP BY

    对字段进行分组,相同字段则会显示在同一行中。

    GROUP BY 进行分组的语句一定要在 SELECT 语句中查询出来。

    SELECT 中可以使用的函数

    函数功能
    AVG取平均值
    COUNT取数据的总数
    MAX取最大值
    MIN取最小值
    STDDEV取标准偏差
    SUM取合计

    举个例子:

    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.
    

    注意:使用 SUM 函数时,使用 CORRESPONDING FIELDS OF 语句会取不到预期的效果。此时需要 AS 起别名。

    SELECT CARRID SUM( PRICE ) AS PRICE 
    	FROM SFLIGHT 
    	INTO CORRESPONDING FIELDS OF TABLE GT_GLT 
    	WHERE CARRID = 'AA'.
    
  11. HAVING

    对 GROUP BY 分组后的数据进行过滤。

  12. SORT 语句

    对指定字段进行排序。

    例如:

    ORDER BY PRIMARY KEY

    • 根据表的 KEY 进行排序。
    • 只适用于 SELECT * 语句
    • 在 JOIN 语句和视图中无法使用。

    ORDER BY 使用 ASCENDING , DESCENDING 语句可以指定排序类型。

    也可以动态的定义要排序的字段,和 SELECT 要动态查询的字段一样,类型为 char 且长度不能超过 72 位。

  13. 嵌套语句

使用 IN 时,嵌套的 SELECT 语句只能返回一个字段,嵌套的语句以嵌套循环的方式执行,执行的次数时嵌套语句执行的行数。

使用 EXISTS 时,存在数据返回 TRUE ,不存在返回 FALSE。

1.4 OPEN SQL——INSERT/MODIFY

1.4.1 INSERT 语句

往数据库里追加一个或者多个数据。

'格式
INSERT INTO <target> <lines>.

指定客户( Client ),可以静态和动态的定义表名。

'格式
INSERT INTO dbtab [CLIENT SPECIFIED] <lines>.
INSERT INTO <name> [CLIENT SPECIFIED] <lines>.

'例如
INSERT INTO ZCUSTOMERS
  CLIENT SPECIFIED
  (CustomerID, FirstName, LastName, Email)
  VALUES ('C002', 'Alice', 'Smith', 'alice.smith@example.com').

  1. 追加一条数据, 结构要与表中的表结构相同。

    ' 将 <wa> 插入到<target>中
    INSERT INTO <target> VALUES <wa>.
    
    INSERT <target> FROM <wa>.
    
    '<dbtab> 要事先以TABLES: <dbtab>
    INSERT <dbtab>.
    
  2. 多条数据

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

    INSERT spfli FROM TABLE gt_spfli ACCEPTING DUPLICATE KEYS.
    

1.4.2 MODIFY 语句

存在数据就会修改,不存在就会插入。

'格式
MODIFY <target> <lines>.

指定客户( Client ),可以静态和动态的定义表名。

'格式
MODIFY dbtab [CLIENT SPECIFIED] <lines>.
MODIFY <name> [CLIENT SPECIFIED] <lines>.
  1. 一条数据

    工作区 要与表

    MODIFY <target> FROM <lines>.
    
    '<dbtab> 要事先以TABLES: <dbtab>定义好表
    MODIFY <dbtab>.
    
  2. 多条数据

    可以一次性修改或追加内表的所有值。

    MODIFY <target> FROM TABLE <itab>.
    
    '下面是一个例子
    DATA: gt_spfli TYPE TABLE OF spfli,
    	gs_spfli TYPE spfli.
    	
    gs_spfli-carrid = 'CN'.
    gs_spfli-connid = '0001'.
    gs_spfli-cityfrom = 'Beijing'.
    MODIFY spfli FROM gs_spfli.
    
    gs_spfli-carrid = 'CN'.
    gs_spfli-connid = '0001'.
    gs_spfli-cityfrom = 'Shanghai'.
    APPEND gs_spfli TO gt_spfli.
    
    gs_spfli-carrid = 'CN'.
    gs_spfli-connid = '0003'.
    gs_spfli-cityfrom = 'Shanghai'.
    APPEND gs_spfli TO gt_spfli.
    
    MODIFY spfli FROM TABLE gt_spfli.
    

1.5 UPDATE 语句

UPDATE 语句用于修改数据库表中的一条或多条数据。

用于指定数据库表名,还可以动态的定义。

UPDATE INTO <target> <lines>.
'指定客户( Client ),可以静态和动态的定义表名
UPDATE <dbtab> [CLIENT SPECIFIED] <lines>.
  1. 一条数据

    UPDATE <target> FROM <wa>.	'工作区 <wa> 要与表 <target> 结构相同
    
    '<dbtab> 要事先以TABLES: <dbtab>定义好表
    UPDATE <dbtab>.
    
  2. 多条数据

    '将多条数据在数据库表中修改
    UPDATE <target> FROM TABLE <itab>.
    
    '修改指定字段 使用 set 语句
    UPDATE <target> SET <set1> <set2> WHERE <itab>.
    

1.6 DELETE 语句

删除数据库中的一个或者多条数据。

DELETE <target> <lines>.

'指定客户( Client ),可以静态和动态的定义表名。
DELETE [FROM](<name>) [CLIENT SPECIFIED] <lines>.
DELETE <dbtab> [CLIENT SPECIFIED] <lines>.
  1. 删除一条数据

    DELETE <target> FROM <wa>.	'工作区 <wa> 要与表 <target> 结构相同
    
    '<dbtab> 要事先以TABLES: <dbtab>定义好表
    DELETE <dbtab>.
    
  2. 删除多条数据

    DELETE FROM <target> WHERE <cond>.
    

    '修改指定字段 使用 set 语句
    UPDATE SET WHERE .

    
    

1.6 DELETE 语句

删除数据库中的一个或者多条数据。

DELETE <target> <lines>.

'指定客户( Client ),可以静态和动态的定义表名。
DELETE [FROM](<name>) [CLIENT SPECIFIED] <lines>.
DELETE <dbtab> [CLIENT SPECIFIED] <lines>.
  1. 删除一条数据

    DELETE <target> FROM <wa>.	'工作区 <wa> 要与表 <target> 结构相同
    
    '<dbtab> 要事先以TABLES: <dbtab>定义好表
    DELETE <dbtab>.
    
  2. 删除多条数据

    DELETE FROM <target> WHERE <cond>.
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值