본문 바로가기

어쩌다 SAP/어쩌다 ABAP

4일차-1) OPEN SQL데이터 읽기

Ⅰ. 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-5> 결과창

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