SAP Open SQL
– 表現層(Presentation),應用層(Application),資料層(Database)
就發生在 Application 和 Database 之間;
SAP Application將傳送的請求,與Database進行匹配,轉換成接受的SQL語句,
DB再執行SQL,將結果返回給Application。
在ABAP程式中有兩種方式訪問資料庫:Open SQL 和Native SQL
1.1 Open SQL 是完全整合到 ABAP語言中的 Standard SQL的子集。它通過資料庫介面將 Open SQL 轉換成 Standard SQL,
所以它可以用相同的方式訪問不同的資料庫系統,然後由該介面把
Open SQL 包含Standard SQL的資料操作語言Data Manipulation Language (DML)部分,允許你讀取和修改資料。
Data Definition Language (DDL) 和 Data Control Language (DCL) 部分使用ABAP Dictionary處理。
1.2 Native SQL 語法不會使用資料庫介面進行轉換,它直接訪問資料庫,所以一個SQL只能訪問一個指定資料庫,
且具有一定的安全風險,對SAP執行效率也會有較大影響,所以一般不推薦使用。
2. Open SQL 語句
Open SQL包含的DML語法有4種:SELECT, INSERT, UPDATE, DELETE, MODIFY
SELECT: 查詢語法
INSERT: 插入資料語法
UPDATE: 更新資料語法
DELETE: 刪除資料語法
MODIFY: 修改資料語法,相當於 INSERT + UPDATE
修改資料前會先在資料庫查詢是否存在該記錄,如果存在則修改,不存在則插入新的資料
Open SQL執行成功後,會返回程式碼 SY-SUBRC = 0, 如果失敗 SY-SUBRC <> 0
除 SELECT 以外的命令,其他都會涉及到資料的修改,要謹慎使用。
在系統標準表中,我們只允許用 SELECT
如若要修改系統標準表,只能通過系統標準程式去操作。
3. SELECT
SELECT 命令包含如下從句:
SELECT: 需要查詢資料庫指定表的那些列,是一行還是多行
INTO: 查詢的結果儲存在哪裡
FROM: 從哪些表查詢數
WHERE: 指定查詢條件
GROUP BY: 以哪些欄位進行分組
ORDER BY: 以哪些欄位進行排序.
3.1 SELECT SINGLE 命令
SELECT SINGLE 命令允許你查詢一條記錄 ,為了確保你查詢的記錄是唯一的,你必須在你的 WHERE 子句指定所有KEY值,
如若查詢的記錄不止一條,系統會返回程式碼 SY-SUBRC = 8,查詢結果為空;
SELECT SINGLE <F1> <F2> FROM <dbtab>
INTO <work area>
INTO (<f1>, <f2>, <f3> … )
INTO CORRESPONDING FIELDS OF <work area>
WHERE <Key1> <op> AND <Key2> <op> …
在INTO中使用 CORRESPONDING FIELDS OF,系統只填充與你的Work Area相同名稱的欄位值;
執行成功返回程式碼 SY-SUBRC = 0,如果失敗SY-SUBRC <> 0。
示例:
12345678 | TABLES: spfli. wa_spfli LIKE spfli. SELECT SINGLE Carrid connid airpfrom airpto FROM spfli INTO CORRESPONDING FIELDS OF wa_spfli WHERE carrid = 'UA' AND connid = '3504' . |
3.2 SELECT 查詢多條記錄
SELECT 查詢多條記錄有兩種方式:
1.使用SELECT … ENDSELECT命令,進行迴圈處理;
2.一次性讀取多筆記錄到內表中,在 INTO 使用TABLE附加字
第一種方式語法格式:
SELECT <F1> … <Fn> FROM <dbtab>
INTO <work area>
INTO (<f1>, <f2>, <f3> … )
INTO CORRESPONDING FIELDS OF <work area>
WHERE <tabfield> <operator> <value>.
ENDSELECT.
第二種方式語法格式:
SELECT <f1> … <fn> FROM <dbtab>
INTO TABLE <itab>
WHERE …
示例:
010203040506070809101112131415 | DATA tab_spfli TYPE STANDARD TABLE OF spfli. DATA wa_spfli LIKE spfli. SELECT carrid connid airpfrom airpto FROM spfli INTO wa_spfli WHERE carrid = 'LH' AND connid = '400' . ENDSELECT . SELECT carrid connid airpfrom airpto FROM spfli INTO CORRESPONDING TABLE OF tab_spfli WHERE carrid = 'LH' AND connid = '400' . |
注意:使用 SELECT… ENDSELECT 語法中不能加入 SINGLE、INTO CORRESPONDING FIELDS 、TABLE等關鍵字,
中間可以使用 CHECK 語法來判斷查詢值。
3.3 SELECT 附加選項
SINGLE [FOR UPDATE]: 使用它會產生一個排他鎖,其他程式不能查詢此筆記錄。
示例:
123456 | * 星號表示查詢所有欄位 SELECT SINGLE FOR UPDATE * FROM SCARR WHERE currcode = 'USD' . WRITE : / scarr-CARRID. |
DISTINCT:查詢非重複記錄,需要使用ORDER BY排序
3.4 SELECT標準函式
在使用 SELECT 語句時,可以直接使用Open SQL提供的標準函式進行相關操作,常用的標準函式有以下幾種:
1.COUNT(): 統計查詢記錄總數
2.SUM(): 彙總某查詢數字欄位數量
3.AVG():計算某查詢數字欄位平均值
4.MAX():查詢表中記錄最大值
5.MIN():查詢表中記錄最小值
使用這些函式時,如果要包含其他欄位,必須使用GROUP BY命令
3.5 FROM 子句
1. FROM dbtab [AS alias] - AS 附加字,用於對 Table另起別名
2. JOIN 聯合查詢
JOIN的聯合查詢有兩種, INNER JOIN 和 LEFT/RIGHT [OUTER] JOIN
通過ON 語句關聯2個或2個以上的表,且必須至少指定一個連線條件;在多個連線條件時,可以使用AND;
ON左右的條件只能使用 = (EQ) 進行連線。
示例:
123 | SELECT SINGLE B~BUKRS FROM BSEG AS B INNER JOIN T001 AS T ON B~BUKRS = T~BUKRS. |
其中,INNER JOIN 與 LEFT/RIGHT JOIN 的區別:
INNER JOIN的 ON 條件下,兩個表資料必須完全匹配;
LEFT JOIN 的 ON 條件下,左邊的表需滿足,右邊的表不用完全匹配。
3. BYPASSING BUFFER - 繞過 Application Buffer,直接讀取資料庫。
4. UP TO n ROWS - 查詢n 筆記錄,限制讀取資料的條數,即只讀取查詢資料的前5條記錄。
3.6 WHERE 子句
WHERE 關鍵字後,可帶子句包括:
1. <field> OP g
OP包括:=, EQ, <>, NE, <, LT, >, GT, <, LE, >=, GE, <=, LE等關係操作符
2. <field> [NOT] BETWEEN g1 AND g2 : 包含 g1 和 g2
示例:
0102030405060708091011 | * Between 的演示 SELECT carrid INTO TABLE itab FROM scarr WHERE carrid BETWEEN 'AA' AND 'AZ' . LOOP AT ITAB. WRITE : / ITAB-CARRID. ENDLOOP . |
3. <field> [NOT] LIKE g :通過萬用字元(‘_’, ’%’)模糊查詢
示例:
12345678 | SELECT * FROM mara WHERE matnr LIKE ‘101-%’. * WHERE matnr LIKE ‘101-___’. WRITE : / mara-matnr. ENDSELECT . |
這裡強烈建議,儘量避免使用LIKE語法作為條件篩選,因為模糊查詢的資料量多數時候會非常龐大;
這樣會直接消耗系統資源,影響系統性能。
4. <field> [NOT] IN ( g1, …, gn ) : 多個組合作為篩選條件
5. <field> [NOT] IN itab : 使用Range table作為篩選條件
6. <field> IS [NOT] NULL :篩選某欄位是否為空
由於內表可以臨時儲存多條資料,而Open SQL允許將內表資料作為查詢條件,故可以通過 語句參照內表作為條件查詢。
相當於使用 INNER JOIN 連線兩個表一樣,然後在資料量龐大的時候,會比INNER JOIN的查詢快捷。
兩者各有優缺點,視具體情況而定。
示例:
0102030405060708091011121314151617181920 | * INNER JOIN 用法: SELECT DISTINCT knb1~bukrs t001~butxt FROM knb1 INNER JOIN t001 ON knb1~bukrs = t001~bukrs INTO CORRESPONDING FIELDS OF TABLE tb_bukrs WHERE kunnr IN rn_kunnr. * FOR ALL ENTRIES IN用法: SELECT DISTINCT bukrs INTO CORRESPONDING FIELDS OF TABLE gt_knb1 FROM knb1. IF gt_knb1[] IS NOT INITIAL . SELECT DISTINCT butxt FROM t001 INTO CORRESPONDING FIELDS OF TABLE gt_too1 FOR A LL ENTRIES IN gt_knb1 WHERE bukrs = gt_knb1-bukrs. END IF . |
注意事項:
1.使用該語句,對於最後得到的結果集,系統會自動刪除重複行。
因此如果你要保留重複行記錄時,記得在 SELECT 語句中新增足夠鍵值專案(有必要時,增加全部鍵值專案),
以保證結果集中所需重複專案不會被刪除。
(例如選取支付金額時,支付事件可能不同,但金額可能相同,此時一定要注意,以避免錯誤刪除結果記錄。)
2. 後面使用的內部表 itab 如果為空,系統將當前 CLIENT 下所有記錄選出。
因此為避免無意義的檢索,在使用該語句前一定要判斷內部表 itab 是否為空,為空時不執行包含該語句的資料庫檢索處理。
3.由於 itab-f 實際上是作為佔位符被替換,所以內部表 itab 中不要包含 HEADER 行(專案標識名稱行),以免造成混淆,檢索出錯。
4.內部表itab中作為條件替換用專案的型別和長度,一定要和檢索資料庫中對應的專案相同,否則編譯不能通過。
5.對於內部表 itab中 作為條件替換用專案,不能使用 LIKE,BETWEEN,IN 比較操作符。
6.使用該語句時,ORDER BY 語句和 HAVING 語句將不能使用。
7.使用該語句時,除COUNT( * )以外的所有標準合計函式(MAX,MIN,AVG,SUM)都不能使用。
4. INSERT 語句
INSERT語法結構:
INSERT INTO <dbtab> VALUES wa.
INSERT <dbtab> FROM TABLE itab.
示例1:
0102030405060708091011 | TABLES scustom. scustom-mandt = '002' . scustom-id = '12400177' . scustom-name = 'Robinson' . scustom-postcode = '69542' . scustom-city = 'Heidelberg' . scustom-custtype = 'P' . scustom-discount = '003' . scustom-telephone = '01234/56789' . INSERT INTO scustom CLIENT SPECIFIED VALUES scustom. |
CLIENT SPECIFIED: 是否指定 CLIENT
如果指定CLIENT,則只插入指定CLIENT的相關資料;
如果用在WHERE語句,則是抽取指定CLIENT的相關資料;如若沒有指定CLIENT,則抽取所有CLIENT的資料。
示例2:
010203040506070809101112131415161718192021222324 | TABLES SPFLI. DATA ITAB LIKE SPFLI OCCURS 10 WITH HEADER LINE . ITAB-CARRID = 'UA' . ITAB-CONNID = '0011' . ITAB-CITYFROM = .. APPEND ITAB. ITAB-CARRID = 'LH' . ITAB-CONNID = '1245' . ITAB-CITYFROM = .. APPEND ITAB. ITAB-CARRID = 'AA' . ITAB-CONNID = '4574' . ITAB-CITYFROM = .. APPEND ITAB. ................ INSERT SPFLI FROM TABLE ITAB ACCEPTING DUPLICATE KEYS . IF SY-SUBRC = 0. ..... ELSEIF -SUBRC = 4. ..... ENDIF . |
5.UPDATE語句
1. UPDATE <dbtab> SET f1 … fn [WHERE sql_cond] .
2. UPDATE <dbtab> FROM TABLE itab [WHERE sql_cond] .
示例:
0102030405060708091011 | UPDATE scustom SET : DISCOUNT = '003' , TELEPHONE = '0621/444444' WHERE ID = '00017777' . TABLES scustom. DATA wa LIKE scustom. wa-id = '12400177' . wa-telephone = '06201/44889' . UPDATE scustom FROM wa. |
6. MODIFY語句
1.MODIFY <dbtab>. (相當於INSERT 和UPDATE)
2.MODIFY <dbtab> FROM TABLE itab.
示例:
01020304050607080910 | TABLES scustom. scustom-id = '12400177' . scustom-name = 'Robinson' . scustom-postcode = '69542' . scustom-city = 'Heidelberg' . scustom-custtype = 'P' . scustom-discount = '003' . scustom-telephone = '06201/44889' . MODIFY scustom. |
7. DELETE語句
1. DELETE FROM <dbtab> WHERE cond.
2. DELETE <dbtab> FROM TABLE itab.
Delete 最好有條件限定,謹慎使用,避免誤刪資料
1 | DELETE FROM SBOOK WHERE CARRID = 'LH' AND CONNID = '0400' AND FLDATE = '19950228' . |