개념 :

Internal Table은 프로그램 내에서 정의하여 사용할 수 있는 Local Table이다. 

ABAP프로그램 내에서 데이터를 임시로 저장하고 처리하기 위한 메모리 테이블이다. = 여러행의 데이터를 담는 배열 구조.

C언어의 구조체+배열을 합쳐놓은 개념과 비슷하다 

 

struct Flight {
    char carrid[3];
    int connid;
    float price;
};

struct Flight flightList[100]; // 구조체 배열

- Flight 는 하나의 행구조 (=work Area)

- FlightLIST는 여러 행을 담는 배열 (= InternalTable)

TYPES: BEGIN OF ty_flight,
         carrid TYPE sflight-carrid,
         connid TYPE sflight-connid,
         price  TYPE sflight-price,
       END OF ty_flight.

DATA: gt_flight TYPE STANDARD TABLE OF ty_flight, " Internal Table (구조체 배열)
      gs_flight TYPE ty_flight.

- ty_flight는 C의 Struct와 같고,

- gt_flight는 struct배열,

- gs_flight 는 struct 하나와 같다. 

* 물론 C언어의 구조체는 고정 크기이기 때문에 정적이라는 것과 ABAP Internal table은 크기가 유동적이라 동적이라는 차이점이 있다.

- 메모리 관리 또한 C언어는 개발자가 malloc해제를 해줘야하지만, ABAP 인터널 테이블은 garbage collection이 없는관계로 자동 처리가 된다. 

구분C 언어 구조체+배열ABAP Internal Table

구문 C언어  ABAP언어
선언 방식 정적 (고정 크기)
STRUCT 구조체[건수] {};
동적 (크기 유동적)
DATA 테이블명 TYPE 테이블 타입.
INITIAL SIZE 건수.
값 할당
flight[1].name = 'Korea',
flight[2].name = 'Asiana'

flight-name = 'Korea'.
APPEND flight.
flight-name = 'Asiana'.
APPEND flight.
값사용 PRINTF( flight[1].name )
PRINTF( flight[2].name )
LOOP AT flight.
   WRITE flight-name.
ENDLOOP.

 

- Internal Table은 동적인 구조체 배열이다.

- Initial size 구문은 실제로 메모리 공간을 할당하는 것이 아닌, 예약 Reserve를 한다.

- 아밥에서는 할당과 추가구문이 쌍으로 움직여야한다.

 

Internal Table생성 

- 인터널 테이블은 구조체 타입을 정의하고 나서 그 타입을 참고하여 생성하는 것이 일반적이다.

- Local Table Type을 이용한 인터널 테이블 생성

- Global ABAP Dictionary TYPE을 이용한 인터널 테이블 생성

 

Local Table TYPE을 이용한 인터널 테이블 생성

TYPES : BEGIN OF t_str,
	~~~
    	END of t_str.

 

TYPES t_itab TYPE STANDARD TABLE OF t_str
	WITH {UNIQUE | NON-UNIQUE} KEY <keys> 
    INITIAL SIZE 100.

 

 

DATA:  gt_itab TYPE t_itab
	[WITH HEADER LINE].

 

 

TYPES: BEGIN OF s_type,
	no(6) TYPE c,
    name(10) TYPE c,
    part(16) TYPE c,
    END OF s_type.
    
 DATA gt_itab TYPE STANDARD TABLE OF s_type WITH NON-UNIQUE KEY no WITH HEADER LINE.
 gt_itab-no = '0001'.
 gt_itab-name = 'Easy ABAP'.
 gt_itab-part = 'SAP'.
 APPEND gt_itab.
 
LOOP AT gt_itab.
 	WRITE: gt_itab-no, gt_itab-name,  gt_itab-part.
ENDLOOP.

 

 

=> 0001 EASY ABAP SAP TEAM

 

 

DATA: BEGIN OF gs_type,
	no(6) TYPE C,
    name(10) TYPE C,
    part(16) TYPE c,
   END OF gs_type.
   
DATA gt_itab LIKE STANDARD TABLE OF gs_type WITH NON-UNIQUE KEY no with header line.

 

- 실제 gt-_itab처럼 선언된 내부 테이블을 다른 변수에서 그대로 재사용하려면 TYPE보다는 LIKE를 많이 씀.=> 정확한 속성 복제때문에.

 

 

GLOBAL ABAP DICTIONARY TYPE을 이용한 인터널 테이블 생성

그 전에 내부테이블에는 세가지 종류가 있다.

종류 특징
STANDARD TABLE 기본 타입. 순서대로 저장. 중복 가능. 느림.
SORTED TABLE 정렬된 상태 유지. 중복 방지(UNIQUE). 빠른 검색.
HASHED TABLE 해시 알고리즘으로 빠른 검색. 중복 불가. 정렬 없음.

- 셋다 특징은 다른데 같은 내부테이블의 종류임

 

- ABAP DICTIONARY 테이블이나 구조체를 참고해서 인터널 테이블을 생성하는 방법

sorted table에 대한 결과물!

- 1 2 

- 2 4

- 3 6 이 출력된다-!

 

- types로 구조체를 선언하는 것은 마치 열 정의를 하는 것과 비슷하다.

필드명 타잆 설명
name string 학생 이름
age integer 학생 나이

 

자주 사용하는 명령어

명령어 설명
APPEND 행 추가
READ TABLE 행 읽기
LOOP AT 반복 처리
MODIFY 수정
DELETE 삭제
CLEAR, REFRESH, FREE 초기화, 메모리 해제

 

APPEND gs_sflight TO gt_sflight. " 행 추가
READ TABLE gt_sflight INTO gs_sflight WITH KEY carrid = 'LH'.
LOOP AT gt_sflight INTO gs_sflight.
  WRITE: / gs_sflight-carrid, gs_sflight-price.
ENDLOOP.

 

 

Internal Table vs DB Table

항목 DB TABLE INTERNAL TABLE
저장 위치 데이터베이스 메모리
지속성 영구적 일시적 (프로그램 종료 시 삭제)
역할 실제 데이터 저장 임시 작업용, 데이터 처리

                                           

 

1. Function Module (함수 모듈)

 

Function Module은 재사용 가능한 ABAP 코드 블록이다.

전역적으로 정의되어 있어서 어디서든 호출 가능하고, 다양한 입력/출력 파라미터를 주고받을 수 있다.

특징

  • CALL FUNCTION 문으로 호출함
  • SE37 트랜잭션 코드로 생성/관리
  • 예외 처리 가능 (EXCEPTIONS)
  • 모듈화, 재사용성, 캡슐화에 용이

 

2. Function Group (함수 그룹)

 

Function Group은 Function Module을 담는 컨테이너이다.

즉, 여러 개의 관련 Function Module을 하나의 논리 단위로 묶어주는 패키지 같은 개념이다.

 특징

  • SE80 또는 SE37에서 생성
  • 하나의 Function Group 안에 여러 Function Module 존재 가능
  • 해당 그룹에는 공통 전역 변수, 타입, 구조도 선언 가능
  • Function Module끼리 내부에서 이 변수 공유 가능

                                                                                                                                                                                                             

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          

  - 개념: 

ABAP에서 반복되는 코드 블록을 이름 붙여서 재사용할 수 있게 해주는 기능/ 작은 템플릿 함수처럼 쓰이지만, 함수나 서브루틴과 다르게 컴파일 타임에 코드가 삽입된다.

DEFINE <macro_name>
	" 반복코드
END-OF-DEFINITION.

 

같은 WRITE문 여러번 쓰기

DEFINE show_line.
  WRITE: / '------------------------'.
END-OF-DEFINITION.

START-OF-SELECTION.

  WRITE: / 'Start'.
  show_line.
  WRITE: / 'Middle'.
  show_line.
  WRITE: / 'End'.

출력결과:

Start
------------------------
Middle
------------------------
End

 

매개변수 있는 MACRO예시

DEFINE print_name.
  WRITE: / 'Hello', &1.
END-OF-DEFINITION.

print_name 'Konie'.
print_name 'Wonie'.

Hello Konie
Hello Wonie

 

 

항목 PERFORM MACRO
🔧 정의 방식 FORM ... ENDFORM. DEFINE ... END-OF-DEFINITION.
🕐 처리 타이밍 런타임에 호출 컴파일 타임에 코드가 복붙됨
🧠 가독성/디버깅 잘됨 (단위 기능으로 분리, 디버깅 가능) 힘듦 (그냥 코드 복사라 디버깅 어려움)
🔁 재사용 가능성 높음 (다양한 값 전달, 구조 분리) 낮음 (단순 반복 코드 대체)
📦 매개변수 USING, CHANGING, RETURNING 등 지원 &1, &2 … 위치값만 사용
🧬 모듈화 가능성 높음 (다른 프로그램에도 INCLUDE 가능) 낮음 (로컬에 국한됨)
🚫 남용 시 문제 적음 (잘 정리됨) 많음 (가독성 ↓, 예외처리 어려움)
🧪 테스트/디버깅 좋음 (브레이크포인트 가능) 어려움 (브레이크포인트 안 됨)

 

 

그래도 너무 헷갈리는 PERFORM VA MACRO

- PERFORM은 논리단위를 정의하고 호출

- MACRO는 문자열 대체다. (반복적인 구문에 유용함)

- 조건문, 반복문, 로직, 데이터베이스, 유지보수가 중요한 경우에는 PEFRORM을 써야한다!

 

Global-Macro

I

INCLUDE해서 Global Macro받아오면 되는데, 처음에 이렇게 했을 때는 오류가 났다.

그 이유는 바로,

"Each ABAP program can contain only one "REPORT", "PROGRAM", or "FUNCTION-POOL" statement."

이 에러때문이였는데, 하나의 아밥 프로그램에서는 report를 한번만 해야하는데, MACRO에서 report하고 있기 때문.

지우니까 바로 결과물이 잘 나오는 것을 확인할 수 있었다!

 

 

- PARAMETES 구문을 쓰기 때문에 Direct Processing을 하면,

 

이렇게 화면이 구성된다.

P_VAL에 EXIT를 작성하면, WRITE를 쓰고 EXIT하면 위와 같이 결과물이 나온다.

P_VAL에 check를 입력하면,

EXIT문이 없기 때문에 아래 Subroutine~ 구문이 나오고,

아무것도 입력하지 않거나 다른 것을 입력하면

Subroutine~ <- 이 문장이 생긴다

 

 

ABAP 프로그램의 조건분기문

 

1. IF ~ ENDIF 분기문

- 조건문의 논리적인 값을 비교하여 참이면 다음 구문을 실행하고 분기문을 빠져나옴

 

2. CASE ~ ENDCASE 분기문

- 하나의 변수에 여러 개의 값이 존재할 경우, 해당 값마다 실행되는 구문을 다르게 설정하는 구문

CASE 변수.
	WHEN 'val1;.
    ~~
    WHEN 'val2'.
    ~~~
    WHEN OTHERS.
    ~~~
    
 ENDCASE.

 

 

1. DO ... ENDDO.

DO 5 TIMES.
  WRITE: / 'Hello'.
ENDDO.

지정한 횟수만큼 반복하는 구문

- 순환횟수를 지정할 수 있는 구문. 

- 회수를 지정하지 않으면 무한 LOOP수행

- 현재 순환횟수 시스템 변수는 SY-INDEX에 저장된다.

 

 

2. WHILE ... ENDWHILE.

DATA count TYPE i VALUE 1.

WHILE count <= 5.
  WRITE: / count.
  count = count + 1.
ENDWHILE.

조건이 참일 때 계속 반복

- WHILE구문의 다음 표현식이 참이면 반복순환을 지속함

- 현재 순환 횟수는 시스템 변수 SY-INDEX에 저장된다.

 

 

3. LOOP AT ... INTO ... ENDLOOP.

DATA: lt_text TYPE STANDARD TABLE OF string,
      lv_text TYPE string.

APPEND 'Hello' TO lt_text.
APPEND 'World' TO lt_text.

LOOP AT lt_text INTO lv_text.
  WRITE: / lv_text.
ENDLOOP.

- 인터널 테이블의 라인을 차례대로 Work AREA 또는 HEADER LINE으로 이동하는 순환구문

- 현재 순환횟수는 시스템 변수 SY-TABIX에 저장된다. SY-TABIX는 인터널 테이블의 라인 번호다.

주의할점:

- LOOP AT은 내부 테이블이 비어있으면 반복되지 않는다.

- DO 는 무한루프가 될 수 있어서 EXIT or 조건 처리가 필요하다

구문 용도
DO TIMES 정해진 횟수만큼 반복
WHILE 조건이 참인 동안 반복
LOOP AT 내부 테이블을 순서대로 반복

 

 

 

 

 

1. 매개변수 없이 호출

2. 매개변수 있는 서브루틴

3. CHAING으로 값변경

=> 이때는 에러남! gv_msg 위치가 애매한 것 같다.

 

 

1) 내부 Subroutine 호출

DATA: gv_val  TYPE c LENGTH 10 VALUE 'Enjoy',
      gv_val2 TYPE c LENGTH 10 VALUE 'ABAP',
      gv_val3 TYPE c LENGTH 20.

PERFORM concate_string USING gv_val gv_val2
                       CHANGING gv_val3.

FORM concate_string USING    VALUE(p_val1) VALUE(p_val2)
                    CHANGING VALUE(p_val3).
  CONCATENATE p_val1 p_val2 INTO p_val3 SEPARATED BY space.
  PERFORM write_d USING p_val3.
ENDFORM.

FORM write_d USING VALUE(p_val).
  WRITE: / p_val.
ENDFORM.

=> Enjoy ABAP 출력됨

 

2) 외부 Subroutine 호출

 

방금 구현한 내부 concat_string이라는 함수를 사용하자.

 

=> External CALL이 출력된다..! 대박ㅋㅋ

 

=> 출력 Dynamic CALL

- 외부 프로그램의 서브루틴을 호출할 경우 동적으로 지정할 수도 있다! (내부 프로그램도 같은 형태로 사용가능함)

- 동적구문을 사용할 때는 프로그램 이름과 서브루틴 이름을 반, 드, 시.대문자로 지정해야하며, 예제에서는 translate명령으로 대문자로 변환했다.

 

3) LIST를 이용한 Subroutine 호출

 

=> write가 잘된다.

LIST 를 이용해 subroutine을 출력하는 방식은, 오직 Internal Subroutine에만 가능하다 => 파라미터를 사용할 수 없는 단점이 있음

 

 

 

파라미터 타입 정의

 

PERFORM 에서는 TYPE C의 변수 gv_val을 넘기고, FORM구문 내의 파라미터는 TYPE I로 선언하게 되면 구문에러가 발생한다.

- Formal Parameter는 아래 3가지 방법으로 타입을 정의할 수 있다.

1. Generic Type사용

FORM subr CHANGING p_val.

2. Actual Parameter와 같은 타입 사용

FORM subr CHANGING p_val TYPE d.

3. Actual Parameter와 같은 타입의 변수 사용

FORM subr CHANGING p_val LIKE gv_val.

 

파라미터와 구조체 

=> 결과: A B

- formal parameter은 모든 ABAP data type이 허용되기 때문에 구조체도 사용할 수 있다.

- 구조체를 파라미터로 사용할 때는 TYPE, LIKE뿐 아닌 STRUCTURE구문을 이용해 구조체 타입을 정의할 수 있다. 

- 만약 구조체 전달 시, 타입 지정을 하지 않으면 에러가 나기 때문에 이 경우에는 필드심볼을 이용해야한다.

 

파라미터와 인터널 테이블

 

- 마찬가지로 서브루틴의 파라미터 타입을 정의하는 구문에서 인터널 테이블 타입도 사용이 가능하다.

- using, changing 키워드도 사용할 수 있다.

 

 

한번 내가 짜보고 싶어서 gpt한테 문제 내달라고했다.

TYPES : BEGIN OF t_student,
          name TYPE c LENGTH 50,
          time TYPE i,
        END OF t_student.

TYPES : t_itabs TYPE TABLE OF t_student.

DATA : s_itabs TYPE t_itabs,
       tv_str  TYPE t_student.

tv_str-name = 'Minho'.
tv_str-time = 8.
APPEND tv_str TO s_itabs.

tv_str-name = 'JiSoo'.
tv_str-time = 9.
APPEND tv_str TO s_itabs.

tv_str-name = 'Hanao'.
tv_str-time = 7.
APPEND tv_str TO s_itabs.

tv_str-name = 'Hyuno'.
tv_str-time = 10.
APPEND tv_str TO s_itabs.

PERFORM tv_test USING s_itabs.
*&---------------------------------------------------------------------*
*& Form tv_test
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> S_ITABS
*&---------------------------------------------------------------------*
FORM tv_test  USING    p_s_itabs TYPE t_itabs.

  READ TABLE p_s_itabs WITH KEY time = 9 INTO tv_str.
  IF sy-subrc = 0.
    WRITE : tv_str-name.
  ENDIF .

ENDFORM.

 

READ TABLE에서 '>=9' 키워드를 쓰니 에러가 나서 일단 =9 로 출력해봄

jisoo가 나왔다.

알고보니, 정확히 read table ... with key는 정확히 일치하는 한 줄만 찾는 용도라서 조건 비교는 되지 않는다.

 

FORM tv_test  USING    p_s_itabs TYPE t_itabs.

  DATA : lv_str TYPE t_student.

  LOOP AT p_s_itabs INTO lv_str.
    IF lv_str-time >= 9.
      WRITE: / lv_str-name, 'is late!'.
    ENDIF.
  ENDLOOP.

ENDFORM.

 

이와 같이 하면 Jisoo, hyuno 가 late했다고 뜬다. 

TYPE ANY TABLE 키워드

 

- type any table키워드가 나오면, 이렇게 에러가 뜬다.

 

이런식으로 동적 파라미터를 받으면 된다.

 

TABLES 구문

TYPES : BEGIN OF t_str,
          col1 TYPE c,
          col2 TYPE i,
        END OF t_str.

TYPES : t_itab TYPE TABLE OF t_str.

DATA : gt_itab TYPE t_itab.
PERFORM testsitab TABLES gt_itab.
PERFORM writee_data TABLES gt_itab.
*&---------------------------------------------------------------------*
*& Form testsitab
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> GT_ITAB
*&---------------------------------------------------------------------*
FORM testsitab  TABLES   p_itab TYPE t_itab.

  DATA ls_str TYPE t_str.
  ls_str-col1 = 'A'.
  ls_str-col2 = 1.
  APPEND ls_str TO p_itab.

  ls_str-col1 = 'B'.
  ls_str-col2 = 2.
  APPEND ls_str TO p_itab.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form writee_data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> GT_ITAB
*&---------------------------------------------------------------------*
FORM writee_data  TABLES   p_gt_itab LIKE gt_itab.

  DATA ls_str TYPE t_str.
  LOOP AT p_gt_itab INTO ls_str.
    WRITE: / ls_str-col1, ls_str-col2.
  ENDLOOP.

ENDFORM.

- 옛날 구문이기 때문에 USING, CHANGING을 요즘에는 쓰지만, 예전 개발 프로그램과의 호환성을 위해 현재도 많이 사용하고 있다.

 

여기서 testsitab은 t_itab을 받고,

wrtiee_data는 gt_itab을 받는 걸 알 수 있다.

이런 차이는 왜 나는 걸까?

키워드 의미 설명
TYPE 타입 참조 정의된 타입 이름을 기반으로 변수나 파라미터를 정의할 때 사용
LIKE 변수 참조 이미 선언된 실제 변수의 구조나 속성을 그대로 따라감

 

TYPE과 LIKE의 차이가 있기 때문이다.

t_itab은 명확하게 선언된 타입이므로 TYPE뒤에 쓰이며,

gt_itab은 이미 선언된 변수이므로 LIKE뒤에 쓰인다. 

 

 

TYPES : BEGIN OF t_score,
          name  TYPE c LENGTH 50,
          score TYPE i,
        END OF t_score.

DATA : gt_score TYPE TABLE OF t_score,
       gs_score TYPE t_score.

gs_score-name = 'Konie'.
gs_score-score = 96.
APPEND gs_score TO gt_score.

gs_score-name = 'monie'.
gs_score-score = 84.
APPEND gs_score TO gt_score.

gs_score-name = 'yonie'.
gs_score-score = 90.
APPEND gs_score TO gt_score.

gs_score-name = 'tonie'.
gs_score-score = 90.
APPEND gs_score TO gt_score.

PERFORM print_score TABLES gt_score.

*---------------------------------------------------------------------*
*       FORM print_score
*---------------------------------------------------------------------*
FORM print_score  TABLES   pt_score LIKE gt_score.

  DATA: ls_score TYPE t_score.

  SORT pt_score BY score DESCENDING.

  LOOP AT pt_score INTO ls_score.
    IF ls_score-score >= 90.
      WRITE: / ls_score-name, ls_score-score.
    ENDIF.
  ENDLOOP.

ENDFORM.

하다보니, data와 types의 차이가 궁금해졌다...!

 

항목 types data
목적 **자료형(타입)**을 정의함 **실제 변수(데이터)**를 선언함
메모리 ❌ 없음 (정의만 함) ✅ 있음 (메모리 공간 생성됨)
사용 시기 변수 선언 전에 타입 만들 때, 재사용할 타입 정의 실제 프로그램에서 값 담고 싶을 때
예시 TYPES: t_num TYPE i. DATA: gv_num TYPE i.
TYPES: t_score TYPE i.    " t_score는 '정수형 타입' 정의만 함 (메모리 없음)

DATA:  gv_score TYPE t_score.  " 실제 변수 gv_score를 선언하고, 타입은 t_score 사용

 

  • TYPES   만드는 것 (형틀, 설계도)
  • DATA  진짜 값 담는 통 만드는 것 (실제 메모리 공간)

 

 

1. subroutine

(FORM ... ENDFORM.)프로시저처럼 동작하는 코드 블록

 

2. CALL BY VALUE vs CALL BY REFERENCE 

구분 설명
CALL BY VALUE 값만 복사해서 넘김 → 원본에 영향 없음
CALL BY REFERENCE 주소를 넘김원본이 직접 변경됨
FORM my_form USING VALUE(p_val)   " Call by Value
                        p_ref.    " Call by Reference
  • VALUE(p_val) : 값 복사 → 복사본만 바뀜
  • p_ref         : 참조로 전달 → 원본도 바뀜

 

  1. VALUE(...)Call by Value (값에 의한 호출)
  2. USINGCall by Reference (참조에 의한 호출, 읽기 전용의 의미로 자주 사용됨)
  3. CHANGINGCall by Reference (참조에 의한 호출, 값이 변경될 수 있음)

 


Call by value

DATA: gv_val TYPE i VALUE 10,
      gv_ref TYPE i VALUE 10.

PERFORM test_form USING VALUE(gv_val) gv_ref.

WRITE: / 'gv_val:', gv_val,  " 그대로 10
       / 'gv_ref:', gv_ref.  " 바뀜

 

문법 호출 방식
FORM myform USING var. Call by Reference var주소를 넘김 (원본이 바뀜)
FORM myform USING VALUE(var). Call by Value var값만 복사해서 넘김 (원본 안 바뀜)

- call by value와 reference 둘 다 using 키워드를 써서 헷갈렸는데, USING은 단순히 '파라미터를 넘긴다'라는 의미.

- VALUE(...)는 넘기는 방식이 '값 복사' 방식임을 명시

- 값 복사에서는 CHANGING을 못쓰는 이유 =>.changin은 원래 값이 바뀌는 것을 전제로 하는데, call by value는 복사본만 넘기기 때문

 

Call by Reference

PERFORM call_byvref USING gv_val.

FORM call_byvref CHANGING p_val.
	p_val='Value is Changed'.
ENDFORM.

 

- VALUE구문을 사용하지 않으면 USING구문과 CAANGING구문은 모두 call by ref를 이용함

=> 따라서 CHANGiNG을 USING으로 변경해도 같은 결과가 나오고, Perform에서 using사용, form에서 changing을 사용해도 에러가 따로 발생하지 않는다.

- 두 구문의 차이는 가독성 차원일 뿐임

- using : 데이터를 전달한다.

- changing : 데이터를 전달하고 변경한다.

PERFORM call_byref USING gv_val.

FORM call_byvref CHANGING p_val.
	p_val = 'Value is changed'.
ENDFORM.

 

Call by Value and Result란?

**“값을 복사해서 넘기고, 끝날 때 복사한 값을 다시 돌려주는 방식”**

 

📦 1단계:  Value (값 복사)

  • 호출할 때 원래 값의 복사본이 전달
  • 그러니까 FORM 안에서 바꿔도 원래 값은 처음에는 바뀌지 않음

 

📤 2단계:  Result (결과 복사)

 

  • FORM이 끝날 때, 내부에서 바뀐 복사본 값을 원래 변수에 다시 복사해서 덮어씌움
  • 그래서 결과는 반영됨!

 

 

결과값은 위와 같다.

 

 


1. 적중 리스트를 최소화해야한다.

SELECT * FROM sflight
	INTO wa
WHERE carrid = 'LH'.
	WRITE : / wa-carrid.
ENDSELECT.

=> ❌

SELECT * FROM sflight
	INTO wa 
    CHECK wa-carrid = 'LH'.
    WRITE : / wa-carrid.
ENDSELECT.

=> 𝐎

 

2. 전송되는 데이터 양을 최소화해야한다.

SELECT * FROM sflight
	INTO wa
    WHERE carrid = 'LH'.
    WRITE : / wa-carrid.
ENDSELECT.

=> ❌

SELECT carrid FROM sflight
	INTO wa-carrid
    WHERE carrid = 'LH'.
    WRITE : / wa-carrid.
ENDSELECT.

=> 𝐎

SELECT carrid FROM sflight
INTO wa-carrid
WHERE carrid = 'LH'.
IF SY-DBCNT > 10.
EXIT.
ENDIF.
ENDSELECT.

=> ❌

SELECT carrid FROM sflight
Up To 10 ROWS 
	INTO wa-carrid
WHERE carrid = 'LH'.
ENDSELECT.

=> 𝐎

 

3. LOOP에 소요되는 비용을 최소화해야한다.

1. array 기능 활용하기

single insert(update, delete, modify)대신 array INSERT를 사용하는 것이 좋다.

즉, Work Area를 이용해 개별 row마다 테이블에 INSERT하는 것보다 인터널 테이블로 한번에 작업하는 것이 효율적이다.

LOOP AT itab INTO wa.
INSERT INTO sflight
	VALUES wa.
ENDLOOP.

 

=> ❌

INSERT sflight
	FROM TABLE itab.

=> 𝐎

 

2. nested select 구문을 피하자.

inner join, for all entry, subquery사용 권장

 

4. 검색비용을 최소화

SELECT * FROM sflight
	INTO wa
WHERE carrid <> 'LH'.
	AND connid = '0400'.

=> ❌

SELECT * FROM sflgiht INTO wa
WHERE carrid IN
( SELECT carrid 
	FROM scarr
    WHERE carrid <> 'LH')
 AND connid = '0400'.

=> 𝐎

 

5. 데이터베이스 부담제거 

SELECT * FROM sflight
	INTO TABLE itab
WHERE carrid = 'LH'
ORDER BY carrid connid.

=> ❌

SELECT * FROM sflight
	INTO TABLE itab
WHERE carrid = 'LH'.
SORT itab BY carrid connid.

=> 𝐎

 

6. 인덱스에 사용된 필드 모두 기술

- SQL문에 가장 영향을 미치는 것 : 인덱스 where 조건과 테이블 JOIN조건인 ON구문도 인덱스로 구성된 필드를 사용하는 것이 효율적임

- 인덱스에 사용된 모든 필드는 모두 기술하는 게 좋다.

- where 조건에 사용될 carrid 값을 모를 경우에는 range 변수를 이용해 빈 값을 INSERT 하고 SELECT해야 적절하게 인덱스를 활용할 수 있다. 

SELECT * FROM sflight
	INTO TABLE itab
WHERE connid = '0017'
AND fldate = '20140101'.

보다는 r_carrid-sign... 이런식으로 자세하게 세부사항을 찾는게 낫다.

 

7. 정렬은 가급적으로 APPLICATION SERVER에서 실행해야함

- order by구문 보다는 application server에서 인터널 테이블을 sort하는 것이 효율적이다.

 

 

MODIFY는 **테이블의 데이터를 변경(수정)**하거나 **없으면 삽입(Insert)**도 해주는 명령어

 

1. DB 테이블에 MODIFY 하기

DATA: gs_scarr TYPE scarr.

gs_scarr-carrid = 'AA'.
gs_scarr-carrname = 'Modified Airline'.
gs_scarr-url = 'https://www.modified.com'.

MODIFY scarr FROM gs_scarr.

- 단일 행 수정(워크 에어리어 사용)

- scarr 테이블에서 carrid = 'AA'인 레코드를 찾아 수정함

- carrid = 'AA'가 없다면 새로 삽입된다. 

 

 

2. 여러 행 수정 (내부 테이블 사용)

DATA: gt_scarr TYPE STANDARD TABLE OF scarr,
      gs_scarr TYPE scarr.

gs_scarr-carrid = 'AA'.
gs_scarr-carrname = 'Modified AA'.
APPEND gs_scarr TO gt_scarr.

gs_scarr-carrid = 'AF'.
gs_scarr-carrname = 'Modified AF'.
APPEND gs_scarr TO gt_scarr.

MODIFY scarr FROM TABLE gt_scarr.

 

  • 내부 테이블 gt_scarr에 담긴 여러 개의 레코드를 한꺼번에 수정.
  • 마찬가지로, 없으면 추가됨.

 

4. 내부 테이블에서 MODIFY

DATA: gt_itab TYPE STANDARD TABLE OF scarr,
      gs_itab TYPE scarr.

READ TABLE gt_itab INTO gs_itab WITH KEY carrid = 'AA'.
IF sy-subrc = 0.
  gs_itab-carrname = 'Changed from loop'.
  MODIFY gt_itab FROM gs_itab INDEX sy-tabix.
ENDIF.
  • 내부 테이블에서 조건을 만족하는 값을 찾아서 수정.
  • MODIFY ... INDEX sy-tabix는 꼭 READ 결과의 인덱스를 써줘야 함.
문법 설명
MODIFY dbtab FROM wa. DB에서 키 값 기준으로 수정/삽입
MODIFY dbtab FROM TABLE itab. 여러 행 수정 or 삽입
MODIFY itab FROM wa INDEX n. 내부 테이블 n번째 수정

+ Recent posts