-
[Open SQL & Native SQL] SELECTSAP/Abap 2022. 1. 12. 13:17
- [SELECT문 전체 구조]
SELECT <cols> SELECT하고자 하는 테이블의 필드(컬럼)명 나열 INTO <target> SELECT문을 통해 읽어온 데이터를 저장할 타겟변수 지정 FROM <source> SELECT문이 동작할 테이블 지정 WHERE <cond> SELECT하고자 하는 데이터의 조건 지정 GROUP BY <fields> SELECT결과 데이터를 필드단위로 그룹으로 묶어 그룹별 데이터를 구한다. HAVING <cond> GROUP BY의 조건을 지정 ORDER BY <fields> SELECT한 데이터를 정렬할 옵션을 지정 [SELECT 구문]
1) 에스터리스크(*) 기호를 통해 전체 필드를 읽어올 수 있지만, 다른 시스템에 비해 SAP 시스템의 주요 테이블에는 많은 필드가 존재하므로 SELECT * 구문은 전체 프로그램 성능에 큰 영향을 미칠 수 있다.
- SELECT * 구문은 컬럼의 전체 필드를 한번에 읽어오지 못하고, 일정 크기만큼 잘라서 SELECT 결과를 반환한다.
2) Database에서 하나의 라인값을 SELECT할 경우에는 SINGLE 키워드를 사용하고 이때 데이터의 조건이 명확해야한다.
- SELECT SINGLE <cols>
- SELECT SINGLE 할 데이터의 조건이 명확하지 않으면 여러개의 라인 중 임의의 라인을 반환한다.
3) Database에서 여러 라인이 SELECT된 경우 중복값을 제거하기 위해 DISTINCT 키워드를 사용할 수 있다.
- SELECT DISTINCT <cols>
4) Database에서 여러 라인이 SELECT되면 해당 결과는 인터널 테이블(Internal Table)내부 또는 필드 및 구조체에 저장된다.
- 인터널 테이블에 저장
- Abap 메모리에 생성되는 데이터를 저장할 수 있는 가상 테이블을 생성하여 데이터를 임시 저장한다.
- Work area(필드 및 구조체)에 저장
- SELECT된 여러 값 중 하나의 값을 필드 및 구조체에 삽입하고 모든 값을 읽을때 까지 loop를 수행하며, 이 경우 SELECT문 마지막에 ENDSELECT 키워드를 추가해야 한다.
- 여러 컬럼을 한번에 저장하는 인터널 테이블 저장방식에 비해 비효율적이다.
REPORT ZA03_01. DATA : gt_itab TYPE STANDARD TABLE OF sflight, " sflight 테이블과 같은 type의 테이블 gs_wa TYPE sflight. " sflight 테이블 컬럼과 같은 type의 구조체 * 필드 및 구조체를 이용하는 SELECT 구문 SELECT * INTO gs_wa FROM sflight WHERE carrid EQ 'AA'. WRITE :/ gs_wa-carrid, gs_wa-connid. ENDSELECT. * 인터널 테이블을 이용하는 SELECT 구문 SELECT * INTO TABLE gt_itab FROM sflight WHERE carrid EQ 'AA'. * 인터널 테이블에 저장된 데이터를 LOOP처리 LOOP AT gt_itab INTO gs_wa. WRITE :/ gs_wa-carrid, gs_wa-connid. ENDLOOP.
5) AS 키워드를 사용하여 컬럼 명에 Alias(별명)을 지정할 수 있다.
- SELECT <cols> [AS <alias>]
6) SELECT문의 대상이 되는 컬럼을 동적으로 선언할 수 있다.
- 동적 구문을 저장할 변수는 Type c, Length 72의 변수여야 한다.
REPORT ZA03_02. DATA : gt_itab TYPE STANDARD TABLE OF sflight, " sflight table type의 테이블 변수 선언 gs_wa LIKE LINE OF gt_itab, " gt_itab table의 컬럼 형태의 구조체 선언 gs_line(72) TYPE c. " 동적 SELECT 컬럼값 저장을 위한 변수 선언 gs_line = 'carrid connid'. " SELECT 대상 컬럼 지정 SELECT DISTINCT (gs_line) INTO TABLE gt_itab FROM sflight. IF sy-subrc EQ 0. " SELECT구문 정상 동작시 LOOP처리 LOOP AT gt_itab INTO gs_wa. WRITE :/ gs_wa-carrid, gs_wa-connid. ENDLOOP. ENDIF.
- 동적 구문의 길이가 72를 넘는경우 해당 변수를 테이블로 선언하여 사용한다.
REPORT ZA03_02. DATA : gt_itab TYPE STANDARD TABLE OF sflight, " sflight table type의 테이블 변수 선언 gs_wa LIKE LINE OF gt_itab, " gt_itab table의 컬럼 형태의 구조체 선언 gs_line(72) TYPE c, " 동적 SELECT 컬럼값 저장을 위한 변수 선언 gt_list LIKE TABLE OF gs_line(72). " gs_line을 컬럼으로 갖는 table 생성 gs_line = 'carrid connid'. " SELECT 대상 컬럼 지정 APPEND gs_line TO gt_list. " 테이블 gt_list에 gs_line 추가 SELECT DISTINCT (gt_list) INTO TABLE gt_itab FROM sflight. IF sy-subrc EQ 0. " SELECT구문 정상 동작시 LOOP처리 LOOP AT gt_itab INTO gs_wa. WRITE :/ gs_wa-carrid, gs_wa-connid. ENDLOOP. ENDIF.
[INTO 구문]
SELECT구문에서 조회한 결과값을 변수에 저장하는 구문으로 CORRESPONDING FIELDS OF 구문을 통해 SELECT구문의 필드와 동일한 필드에만 값을 할당할 수 있다.
1) Work area(변수 및 구조체)에 저장
- 테이블 내 하나의 컬럼만 조회하는 경우 사용한다.
- SELECT INTO [CORRESPONDING FIELDS OF] <wa>
2) Internal table에 저장
- 테이블 내 다수의 컬럼을 조회하는 경우 사용한다.
- SELECT INTO|APPENDING [CORRESPONDING FIELDS OF] TABLE <itab> [PACKAGE SIZE <n>]
- INTO: 인터널 테이블을 초기화 한 후 데이터를 삽입한다.
- APPENDING: 인터널 테이블을 초기화 하지 않고 추가로 삽입한다.
- PACKAGE SIZE: 인터널 테이블에 삽일할때 몇개의 라인씩 삽입할지 지정한다.
- PACKAGE SIZE 키워드를 이용하는 경우 ENDSELECT 구문을 추가해야 한다.
REPORT ZA03_04. DATA : gs_wa TYPE sflight, gt_itab TYPE TABLE OF sflight. * spfli 테이블의 carrid, connid 필드를 sflight table type의 인터널 테이블에 * 삽입하기 위해 CORRESPONDING FIELDS OF 구문 사용 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) INTO 구문을 통해 특정 변수에 SELECT 결과를 삽입할때는 다음 구문을 사용한다.
- SELECT ... INTO (f1, f2...)
[FROM 구문]
- FROM 구문은 SELECT할 대상 테이블을 지정한다.
- FROM <table> [<option>]
- FROM 구문의 option
CLIENT SPECIFIED 자동 client설정을 해제한다. BYPASSING BUFFER SAP local buffer에서 값을 읽지 않고 바로 DB table에 접근한다. UP TO n ROWS SELECT문의 대상 row개수를 제한한다. => 대량요청으로 인한 성능 저하 방지
1) 정적 테이블 지정
- SELECT ... FROM <dbtab> [AS <alias>] <option>
2) 동적 테이블 지정
- SELECT ... FROM (dbtab).
- 동적으로 지정할 테이블 이름은 반드시 대문자여야하며, Abap dictionary에 존재해야한다.
REPORT ZA03_05. * 동적으로 지정될 테이블이름을 파라미터로 사용자로부터 입력받음 * PARAMETERS 사용시 자동으로 SELECTION SCREE이 생성된다. PARAMETERS p_tname TYPE char10. DATA gs_wa TYPE sflight. SELECT SINGLE * INTO gs_wa FROM (p_tname) WHERE carrid = 'AA'. WRITE :/ gs_wa-carrid, gs_wa-connid.
3) JOIN 구문
- SELECT ... FROM <tab> [INNER] JOIN <dbtab> [AS <alias>] ON <cond> <options>...
- 여러 테이블의 값을 동시에 읽어올 경우 JOIN을 사용한다.
- 이때, 대상이되는 테이블들 간의 연결 조건은 ON구문을 통해 지정하며, 조건에 해당하는 필드에 인덱스가 존재할때 빠른 성능이 보장된다.
- 잘못된 코드: 인터널테이블에 저장된 데이터를 대상으로 LOOP를 돌려 추가 작업을 수행
SELECT field1 INTO gt_itab FROM table1. LOOP AT gt_itab. SELECT field2 INTO gt_iteb-field2 FROM table2 WHERE field1 = gt_itab-field1 MODIFY gt_itab. ENDLOOP.
- 올바른 코드: JOIN연산을 사용
SELECT a~field1 b~field2 INTO gt_itab FROM table1 AS a INNER JOIN table2 AS b ON a~filed1 = b~field1.
- SQL 구문에서는 WHERE 조건이 ON 조건보다 먼저 처리된다.
REPORT ZA03_06. 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.
- OUTER JOIN
- INNER JOIN은 ON조건을 기준으로 두 테이블의 공통데이터를 추출하므로, 특정 테이블 하나에 데이터가 없다면 다른 테이블에 데이터가 존재해도 해당 데이터는 추출되지 않는다.
- OUTER JOIN은 특정 테이블에 다른 테이블에 해당하는 데이터가 없더라도 해당 데이터를 추출하는 연산이다.
- 즉, 아래 프로그램에서는 확인이 어렵지만, 만약 sflight 테이블에 carrid가 'KO'인 데이터가 존재한다면 OUTER JOIN결과 scarr테이블에 'KO'에 해당하는 carrname이 없더라도 'KO'에 대한 데이터가 빈칸으로 조회될 것이다.
REPORT ZA03_07. TYPES: BEGIN OF t_str, carrid TYPE sflight-carrid, carrname TYPE scarr-carrname, END OF t_str. DATA : gs_str TYPE t_str. SELECT DISTINCT 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. WRITE :/ gs_str-carrid, gs_str-carrname. ENDSELECT.
4) Line 수 제한 구문
- SELECT ... FROM <tab> UP TO <n> ROWS ...
- 해당 구문은 테이블의 최대 조회 컬럼수를 제한하기 위해 사용된다.
- SAP 시스템에는 방대한 양의 데이터가 있어 사용자가 조회조건 없이 조회를 한다면 시스템 성능에 영향을 줄 수 있기때문이다.
[WHERE 구문]
- WHERE조건에 사용되는 필드에 인덱스가 존재할때 빠른 성능이 보장된다.
- WHERE구문 연산자
EQ(=) NE(<>, ><) LT(<) LE(<=) GT(>) GE(>=) 같음 같지 않음 보다 작음 보다 작거나 같음 보다 큼 보다 크거나 같음
1) Interval 조건
SELECT ... WHERE <s> [NOT] BETWEEN <f1> AND <f2>
2) String 비교
SELECT ... WHERE <s> LIKE <f1> => Format 비교
3) List value
SELECT ... WHERE <s> [NOT] IN (<f1>, <f2>, ...)
4) Selection table
- 리스트 외에도 IN구문을 통해 Selection table, Range변수에 존재하는 값을 이용한 조회가 가능하다.
- Selection table, range: 인터널 테이블과 같이 여러 row를 저장할 수 있는 변수
SELECT ... WHERE <s> [NOT] IN <seltab>
5) Dynamic(동적) 조건
- SELECT 구문과 마찬가지로 Type c length 72조건을 갖는다.
REPORT ZA03_08. DATA : gs_where TYPE c LENGTH 72, gv_carrname TYPE scarr-carrname, gv_carrid TYPE scarr-carrid VALUE 'AC'. * '': 문자열 변수 내에서 quatation(')을 표현 * gs_where => carrid = 'AC' CONCATENATE 'carrid = ''' gv_carrid '''' INTO gs_where. SELECT SINGLE carrname INTO gv_carrname FROM scarr WHERE (gs_where). WRITE :/ gv_carrname.
- 다수의 동적 조건을 지정할때는 인터널테이블을 사용한다.
REPORT ZA03_09. DATA : gs_where TYPE c LENGTH 72, gt_where LIKE TABLE OF gs_where, " 다수의 동적조건을 위해 인터널테이블 선언 gv_carrname TYPE scarr-carrname, gv_carrid1 TYPE scarr-carrid VALUE 'AC', gv_carrid2 TYPE scarr-carrid VALUE 'AF'. CONCATENATE 'carrid = ''' gv_carrid1 '''' INTO gs_where. APPEND gs_where TO gt_where. " 1번째 조건 추가 gs_where = 'OR'. APPEND gs_where TO gt_where. " 조건 연산자 추가 CONCATENATE 'carrid = ''' gv_carrid2 '''' INTO gs_where. APPEND gs_where TO gt_where. " 2번째 조건 추가 SELECT carrname INTO gv_carrname FROM scarr WHERE (gt_where). WRITE :/ gv_carrname. ENDSELECT.
6) FOR ALL ENTRIES 구문
- SELECT ... FOR ALL ENTRIES IN <itab> WHERE <cond>
- 인터널테이블과 실제 Database의 테이블을 join하는 개념.
REPORT ZA03_10. DATA : gt_spfli TYPE TABLE OF spfli, gt_sflight TYPE TABLE OF sflight, gs_sflight TYPE sflight. SELECT * FROM spfli INTO TABLE gt_spfli. * FOR ALL ENTRIES IN 구문의 gt_spfli 인터널테이블의 필드와 * 실제 Database내 sflight의 필드를 WHERE구문에서 비교 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.
[GROUP BY 구문]
- 테이블의 특정 컬럼의 값을 기준으로 데이터를 요약(집계)하여 조회한다.
- Aggregate(집계) 함수를 사용하기 위해서는 GROUP BY구문이 기술되어야한다.
- GROUP BY구문에 사용된 컬럼은 반드시 SELECT구문에 같은 컬럼으로 기술되어야 한다.
AVG COUNT MAX MIN STDDEV SUM VARIANCE 평균 개수 최대값 최소값 표준편차 합계 분산 REPORT ZA03_11. 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.
- Having 구문: GROUPING 조건
- GROUP BY로 조회한 SELECT 구문에 조건을 추가한다.
- WHERE 조건처럼 동적 선언이 가능하다.
[ORDER BY 구문]
- SELECT ... ORDER BY <f1> [ASCENDING | DESCENDING]
REPORT ZA03_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.
[Subquery]
서브쿼리란, SELECT 문 내부의 WHERE 구문 조건에 또 다른 SELECT 문을 추가하여 조건 비교를 하기위해 사용된다.
1) Scalar Subquery
- 서브쿼리의 결과로 하나의 컬럼 또는 집계(Aggregate)함수 값을 반환하는 서브쿼리
REPORT ZA03_13. 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 = 'AZ'. WRITE :/ gv_carrid, gv_connid, gv_paymentsum.
2) Non-scalar Subquery
- 서브쿼리의 결과가 존재하면 TRUE, 존재하지 않으면 FALSE를 반환하는 서브쿼리.
- 메인쿼리의 WHERE 구문에서 EXISTS를 사용하여 구현한다.
REPORT ZA03_14. 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 = 'AZ'. WRITE :/ gv_carrid, gv_connid, gv_paymentsum.
'SAP > Abap' 카테고리의 다른 글
[Open SQL & Native SQL] SQL else (0) 2022.01.14 [Open SQL & Native SQL] INSERT & UPDATE & DELETE & MODIFY (0) 2022.01.14 [Open SQL & Native SQL] Overview (0) 2022.01.11 [Data Type] Assigning value & 기타변수 선언 (0) 2022.01.11 [Data Type] ABAP dictionary's type (0) 2022.01.11