Ⅰ. SQL의 정의
- SQL이란Structured Query Language의 약자로 관계형 데이터베이스에 사용되는 표준화된 언어이다.
- SQL은 OPEN SQL과 NATIVE SQL 두 가지가 있다.
- OPEN SQL은 ABAP에서만 사용되고, Database Interface를 통해 NATIVE SQL로 번역된다.
- NATIVE SQL은 데이터 베이스에 사용되는 SQL 언어이다.
오늘은 OPEN SQL에 대해서 공부하기로 한다.
Ⅱ. OPEN SQL 이란?
- OPEN SQL은 데이터베이스 데이터를 조회하고 변경하는 등의 기능을 수행한다.
Ⅲ. OPEN SQL : 데이터 읽기
1. SELECT 구문
-SELECT 구문은 데이터 베이스 테이블에서 필요한 데이터를 읽어온다.
1) Single Line
- 데이터베이스에서 하나의 라인 값을 읽어오고자 할 경우 SINGLE을 사용한다.
- SINGLE은 데이터 한 건만을 가져오기 때문에 원하는 데이터의 조건을 정확하게 알고 있어야한다.
- 테이블의 모든 칼럼을읽을 때는 '*'를 사용한다.
SELECT SINGLE <cols> ... WHERE
2) Several Lines
- 여러 라인을 조회할 떄는 SELECT 결과가 Internal Table에 저장된다.
- SELECT / ENDSELECT를 사용하면 조건을 해당하는 값을 모두 읽어 올 때까지 LOOP를 수행한다.
<예제 3-1> - SELECT / ENDSELECT 와 LOOP / ENDLOOP를 통해 Internal Table 만들기
1) SELECT / ENDSELECT
*DATA: gt_itab TYPE STANDARD TABLE OF sflight,
* gs_wa TYPE sflight.
*
*SELECT * INTO gs_wa
* FROM sflight
* WHERE carrid EQ 'AA'.
* WRITE : / gs_wa-carrid,
* gs_wa-connid.
*ENDSELECT. "SELECT / ENDSELECT는 구문이 반복 수행될 때마다 인터페이스가 수행해서 비효율적"
2) LOOP / ENDLOOP
*DATA: gt_itab TYPE STANDARD TABLE OF sflight,
* gs_wa TYPE sflight.
*
*SELECT * INTO TABLE gt_itab
* FROM sflight
* WHERE carrid EQ 'AA'.
*
*LOOP AT gt_itab INTO gs_wa.
* WRITE: / gs_wa-carrid,
* gs_wa-connid.
*ENDLOOP. "LOOP / ENDLOOP는 인터널 테이블에 값을 한 번에 저장하기에 더 효율적"
3) AS (Alias)ㅌ`
SELECT <cols> AS <alias> ... "AS로 칼럼에 별명 지정 가능"
4) 동적인 SELECT 구문
<예제 3-2> - 동적인 SELECT 구문
*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 CORRESPONDING FIELDS OF TABLE gt_itab
* FROM sflight. *IF sy-subrc EQ 0.
* LOOP AT gt_itab INTO gs_wa.
* WRITE : / gs_wa-carrid, gs_wa-connid.
* ENDLOOP.
*ENDIF.
사실 이게 왜 동적인 SELECT라 하는지 아직도 모르겠음.
2. INTO 구문
-SELECT 구문에서 조회한 결괏값을 변수에 저장하는 기능을 수행
1) 구조체(Work Area)
- 여러 칼럼의 한 라인만 조회하고자 하는 경우에 Work Area에 값을 할당.
- CORRESPONDING FIELDS OF 구문 사용하면 한 번에 Work Area의 동일 필드명에 값을 할당.
SELECT ... INTO [CORRESPONDING FIELDS OF] <WA>.
2) Internal table
- 여러 라인을 조회할 경우 인터널 테이블 사용
- APPENDING은 인터널 테이블에 추가로 INSERT한다.
- INTO는 인터널 테이블의 데이터를 삭제한 후 INSERT한다.
SELECT ... INTO / APPENDING [CORRESPONDING FIELDS OF]
TABLE <itab>
[ PACKAGE SIZE <n>]...
END SELECT.
- PACKAGE SIZE : 인터널 테이블에 몇 개의 라인을 추가할 것인가 설정.
<예제 3-4> - Package size 5를 사용해서
*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
- 차이가 뭔지를 모르겠다..?
3. FROM 구문
- FROM 구문은 데이터를 SELECT할 대상 테이블을 지정
- FROM 구문 다음에는 하나의 테이블을 지정하거나 여러 테이블을 JOIN할 수 있다.
SELECT ... FROM table option ...
- UP TO n ROWS : SELECT의 row 개수를 제한한다.
1) 정적인 TABLE 선택 - AS 사용
SELECT ... FROM <dbtab> [AS <alias>] <options>
2) 동적인 TABLE 선택
SELECT ... FROM (dbtab)
<예제 3-5> - 사용자가 출력을 원하는 테이블 이름을 직접 입력받아 데이터를 출력
*PARAMETERS p_tname TYPE char10.
*DATA GS_WA TYPE sflight.
*
*SELECT SINGLE * INTO gs_wa
* FROM (p_tname)
* WHERE carrid = 'AA'.
3) JOIN 구문
- 여러 테이블 값을 동시에 읽어 올 경우 JOIN을 사용.
- Primary Key와 Foreign Key를 사용해서 JOIN하는 경우가 대부분.
- 두 테이블 간 연결 조건은 ON 구문 사용
SELECT ...FROM <tab> [INNER] JOIN <dbtab> [AS <alias>]
on <cond> <options> ...
- ABAP에서는 테이블 간 JOIN 보다 인터널 테이블에 데이터를 저장하고 LOOP 구문을 이용해 추가 정보를 SELECT하여 인터널 테이블 내용을 MODIFY 하는 경우가 많다.
SELECT field1 INTO gt_itab FROM table1.
LOOP AT gt_itab.
SELECT field2 into gt_itab-field2 FROM table2
WHERE field1 = gt_itab-field1.
MODIFY gt_itab.
ENDLOOP.
- 이렇게 LOOP쓰면 프로그램이 느려진다. 따라서 JOIN 쓸 수 있는 경우라면 JOIN을 쓰는 것이 바람직하다.
SELECT a~field1 b~field2 INTO gt_itab
FROM table1 as a, table2 as b
ON a~field1 = b~field1.
- WHERE 조건과 ON구문이 기술되어 있으면, WHERE 조건이 먼저 수행되고, 이 데이터를 기준으로 ON 조건에서 두 테이블을 JOIN한다.
<예제 3-6> - 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 EQ b~carrid
* WHERE a~carrid = 'AA'.
*
*WRITE : gs_str-carrid, gs_str-carrname.
4) INNER JOIN과 OUTER JOIN
SELECT ... FROM <tab> LEFT [OUTER] JOIN <dbtab>
[AS <alias>]
ON <cond>
<options>
<예제 3-7> - 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 OUTER JOIN scarr AS b
* ON a~carrid EQ b~carrid
* WHERE a~carrid = 'AA'.
*
*WRITE : gs_str-carrid, gs_str-carrname.
4. WHERE 구문
- WHERE 조건은 사용자가 원하는 데이터를 정확하게 선택할 수 잇도록 하는 조건이다.
1) Interval 조건
SELECT ... WHERE <s> [NOT ] BETWEEN <f 1> AND <f 2>
2) String 비교
COL2 = 'ABCDEFGHIGJ'.
SELECT ~ WHERE COL2 LIKE 'ABC%'.
- %는 엑셀의 * 처럼 '김*' 하면 '김'으로 시작하는 텍스트를 선택한다.
3) LIST VALUE
- IN 구문을 사용해서 여러 조건에 속한 경우의 값을 가져온다. ex) 'WHERE 거주지 IN ('서울', '수원')'
SELECT ... WHERE <s> [NOT] IN (<f 1>, ... , <f n>) ...
4) SELECTION TABLE
- IN 구문을 사용해 Selection Table, Range 변수에 존재하는 값들을 조회 할 수 있다.
c.f) Selection Table, Range 변수는 인터널테이블처럼 여러 Row를 저장할 수 있는 변수이다.
SELECT ... WHERE <s> [NOT ] IN <seltab> ...
5) Dynamic 조건
- SELECT 구문의 조건을 설정하는 WHERE 구문을 동적으로 구성할 수 잇다.
SELECT ... WHERE (<itab>) ...
<예제 3-9> - dnymaic 조건
*DATA gs_where TYPE 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_carrid2 TYPE 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.
6) FOR ALL ENTRIES 구문
<예제 3-10> - FOL ALL ENTRIES구문 이용해서 일자별 항공기 운항 정보 테이블에서 관련 데이터를 SELECT
*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.
5. GROUPING 구문
- aggregate 함수를 사용하려면 SELECT 구문에 GROUP BY를 기술해야 함.
- GROUP BY 구문은 테이블의 특정 칼럼에 같은 값들이 존재할 때 이 값들의 정보를 요약해서 한 줄의 정보로 조회되게 한다.
SELECT <f1> <f2> <agg> ...
GROUP BY <f1> <f2> ...
<예제 3-11> - 항공기 ID별 평균 예약 점유율을 SELECT 하는 구문을 실습.
*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.
- 결과가 해설과 달라 질문할 필요 있음!
6. GROUPING 조건 : HAVING
- HAVING 구문은 GROUP BY로 조회한 SELECT 구문에 그룹의 조건을 추가한다.
SELECT <f1> <F2> <agg> ...
...
GROUP BY <f1> <f2>
HAVING <cond>.
SELECT carrid connid AVG( paymentsum )
INTO (gv_carrid, gv_connid, gv_paymentsum)
FROM sflight GROUP BY carrid connid
HAVING AVG( paymentsum ) > 100000.
7. SORT 구문
- SELECT 결과로 조회된 데이터가 ORDER BY에 기술된 칼럼 기준으로 정렬
- ORDER BY 사용하지 않으면 임의로 정렬된 결과가 조회된다.
- SELECT * 구문인 경우에만 사용 가능하다.
- JOIN 구문 및 VIEW에는 사용할 수 없다.
- ASCENDING - 오름차순 / DESCENDING - 내림차순
<예제 3-12> - 예약좌석 기준 오름차순으로 정렬
*DATA : gv_carrid TYPE sflight-carrid,
* gv_connid TYPE sflight-connid,
* gv_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.
- 이것도 값이 해답과 달라서 질문 필요
8. Subquery
- Subquery는 SELECT 구문의 WHERE 조건에 또 다른 SELECT 구문을 추가하여 값을 제한하는 목적으로 사용
1) Scalar Subquery
- Select 절 안에 기술된 SELECT 절 (JOIN과 비슷한 역할)
<예제 3-13> - Scalar 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.
2) Non-scalar Subquery
- Subquery 결과가 존재하면 TRUE / 존재하지 않으면 FALSE
- EXISTS 구문을 이용해 구현
<예제 3-14> - Non-scalar 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 EXISTS ( SELECT *
* FROM spfli
* WHERE carrid = a~carrid
* AND connid = a~connid )
* AND a~carrid = 'AA'.
*
* WRITE : gv_carrid, gv_connid, gv_paymentsum.
출처: https://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788965400288
Easy ABAP 2.0 - 교보문고
기본 이론과 실무 예제로 새롭게 꾸민『Easy ABAP 2.0』. 기본 이론과 예제 프로그램의 실습으로 단계적으로 ABAP 프로그램을 완성해갈 수 있도록 구성된 교재이다. 이론 부분은 1장 ~ 11장으로 구성��
www.kyobobook.co.kr
'어쩌다 SAP > 어쩌다 ABAP' 카테고리의 다른 글
5일차) NATIVE SQL (0) | 2020.08.28 |
---|---|
4일차-2) OPEN SQL: 데이터 변경 (0) | 2020.08.28 |
3일차) Assigning Value, 기타 변수 선언 (0) | 2020.08.26 |
2일차) Predefined ABAP Type, 프로그램의 Local Type, Type ABAP Dictionary의 Type (0) | 2020.08.25 |
1일차) SAP란, ABAP 정의, DATA 타입 종류, 선언 방법 (1) | 2020.08.25 |