본문 바로가기

SAP&ABAP/ABAP

EASY ABAP - 10. FIELD SYMBOL(필드 심볼)

728x90

FIELD SYMBOL이란?

- 특정 데이터 오브젝트를 가리킬 수 있는 포인터

 

FIELD SYMBOL의 특징

- ABAP 프로그램 내에서 변수에 동적인 접근 가능

- 자기 자신을 위한 메모리 공간 점유 하지 않음

- 데이터 이름과 속성은 실행 시점(RUNTIME)에 결정

- 모든 데이터 오브젝트에 지정 가능

- 일단 필드 심볼이 할당되면 데이터 오브젝트와 필드 심볼 간에는 차이가 없다(필드 심볼 변경이 곧 데이터 오브젝트 변경)

- MOVE와 같은 ABAP 명령어 사용 가능

- 필드 심볼은 타입을 명시 혹은 명시하지 않고도 생성할 수 있다. 타입이 명시되지 않으면 할당되는 오브젝트의 타입을 그대로 상속받는다.

 

FIELD SYMBOL 메커니즘(그림)

- 필드 심볼에 할당되면 같은 메모리 주소를 할당받기 때문에 필드 심볼이 곧 해당 데이터 오브젝트를 가리키는 변수가 된다.

- 즉 필드 심볼을 이용하여 변수값을 변경하는 것과 기존 변수명을 이용하여 변수값을 변경하는 것은 차이가 없다.

- ASSIGN을 만나면 아무 것도 가리키고 있지 않은 필드 심볼이라는 포인터가 특정 데이터 오브젝트를 가리키는 포인터가 된다.

 

DATA : BEGIN OF LINE,
    COL1(12) VALUE '1234567890AB',
END OF LINE.

FIELD-SYMBOLS : <FS>.

ASSIGN LINE-COL1+6(*) TO <FS>.
WRITE : / <FS>.

결과 : 7890AB

 

필드 심볼 선언

1. Generic Type Field Symbol

- 필드 심볼을 선언할 때 타입을 지정하지 않고, 할당되는 데이터 오브젝트 유형에 따라 속성을 상속받는다.

FIELD-SYMBOLS : <FS1>.
FIELD-SYMBOLS : <FS2> TYPE ANY.
FIELD-SYMBOLS : <FS2> TYPE ANY TABLE.

- TYPE ANY TABLE을 쓰려면 할당할 데이터 오브젝트가 인터널 테이블이어야 한다.

- TABLE 키워드가 없으면 LINE타입의 구조체로 활용할 수 있다.

 

2. Fully Type Field Symbol

- 필드 심볼을 정의할 때 타입이 정해진 형태로 선언

- 같은 속성의 데이터 오브젝트를 할당받아야 한다.

FIELD-SYMBOLS : <FS1> TYPE GT_TAB.
FIELD-SYMBOLS : <FS2> LIKE LINE OF GT_TAB.
FIELD-SYMBOLS : <FS3> LIKE GT_TAB.

- GT_TAB이 헤더라인이 있는 인터널 테이블이라면 3개의 필드 심볼은 차이가 없다.

 

LIKE와 LIKE LINE OF의 차이점

- GT_TAB이 HEADER LINE이 있느냐 없느냐에 따라 차이가 발생한다. HEADER LINE이 없다면 <FS3>은 인터널 테이블을 가리키는 필드 심볼을 선언하게 된다. 헷갈리므로 LIKE 구문은 자제하는 게 좋다.

 

 

 

ASSIGN 구문 동적 사용

" 구조체 선언
DATA : BEGIN OF GS_STR,
  COL1 TYPE CHAR5  VALUE 'KOREA',
  COL2 TYPE CHAR10 VALUE 'SEOUL',
  COL3 TYPE CHAR15 VALUE 'TWIN BUILDDING',
END OF GS_STR.

" 필드명을 담을 변수 선언
DATA : GV_FNAME TYPE C LENGTH 10.
DATA : GV_IDX   TYPE N.

FIELD-SYMBOLS : <FS1> LIKE GS_STR. " 구조체 가리킬 필드 심볼
FIELD-SYMBOLS : <FS2> TYPE ANY.    " 구조체의 각 필드를 가리킬 필드 심볼

ASSIGN GS_STR TO <FS1>. " 구조체 할당

DO 3 TIMES.

  CLEAR : GV_FNAME.
  GV_IDX = SY-INDEX.
  GV_FNAME = 'COL'.
  CONCATENATE GV_FNAME GV_IDX INTO GV_FNAME. " 필드명 동적 생성

  ASSIGN COMPONENT GV_FNAME OF STRUCTURE <FS1> TO <FS2>. " 구조체 <FS1>의 필드를 변수를 통해 지정하여 <FS2>에 할당
  WRITE : / <FS2>.

ENDDO.

 

필드 심볼과 CASTING(형변환)

- 데이터 오브젝트를 필드 심볼에 ASSIGN 할 경우에, CASTING(형변환)를 이용해 모든 데이터 타입을 필드 심볼에 할당할 수 있다.

- 암묵적 형변환과 명시적 형변환 2가지가 있다.

 

1. 암묵적 형변환(Implicit Casting)

- 타입이 정해진 필드 심볼과 데이터 오브젝트 타입이 서로 다른 경우 CASTING 키워드를 이용하여 ASSIGN 해야 한다.

ASSIGN GV_ADDR TO <FS> CASTING.

 

2. 명시적 형변환(Explicit Casting)

- 필드 심볼을 Generic Type으로 선언한 경우 Casting 시 TYPE을 지정하여 ASSIGN 해야 한다.

FIELD-SYMBOLS : <FS1> TYPE ANY.
ASSIGN ADDR TO <FS1> CASTING TYPE T_ADDR.

 

필드 심볼과 인터널 테이블

- 필드 심볼을 이용하여 인터널 테이블을 변경하게 되면 Work Area로 복사하는 과정이 생략되어 성능이 향상된다.

DATA : BEGIN OF GS_LINE,
  CARRID TYPE SFLIGHT-CARRID,
  CONNID TYPE SFLIGHT-CONNID,
  CARRNAME TYPE SCARR-CARRNAME,
END OF GS_LINE.

DATA : GT_ITAB LIKE TABLE OF GS_LINE.
FIELD-SYMBOLS : <FS> LIKE GS_LINE.

SELECT CARRID CONNID
  INTO CORRESPONDING FIELDS OF TABLE GT_ITAB
  FROM SFLIGHT.

LOOP AT GT_ITAB ASSIGNING <FS>.

  SELECT SINGLE CARRNAME INTO <FS>-CARRNAME
    FROM SCARR WHERE CARRID = <FS>-CARRID.

  WRITE : / <FS>.
ENDLOOP.

 

 

DATA : BEGIN OF GS_LINE,
  CARRID TYPE SFLIGHT-CARRID,
  CONNID TYPE SFLIGHT-CONNID,
  CARRNAME TYPE SCARR-CARRNAME,
END OF GS_LINE.

DATA : GT_ITAB LIKE TABLE OF GS_LINE.
FIELD-SYMBOLS : <FS> LIKE GS_LINE.

SELECT CARRID CONNID
  INTO CORRESPONDING FIELDS OF TABLE GT_ITAB
  FROM SFLIGHT.

LOOP AT GT_ITAB ASSIGNING <FS>. " 필드 심볼에 할당

  SELECT SINGLE CARRNAME INTO <FS>-CARRNAME
    FROM SCARR WHERE CARRID = <FS>-CARRID.
 
  " 인터널테이블에 그대로 넣고 MODIFY 구문 없이도 인터널 테이블 변경됨
  " EX) MODIFY GT_ITAB FROM GS_ITAB <= 이런 구문 없어도 인터널 테이블 변경됨.
 
  WRITE : / <FS>.
ENDLOOP.

필드 심볼의 경우 WORK AREA를 거치지 않는다 = 메모리에 저장된 값을 바로 변경한다.

 

필드 심볼 활용

DATA : GS_COSP TYPE COSP. " 월별 데이터가 있는 구조체 선언

GS_COSP-WTG001 = 100.
GS_COSP-WTG002 = 200.
GS_COSP-WTG003 = 300.
GS_COSP-WTG004 = 400.
GS_COSP-WTG005 = 500.
GS_COSP-WTG006 = 600.
GS_COSP-WTG007 = 700.
GS_COSP-WTG008 = 800.
GS_COSP-WTG009 = 900.
GS_COSP-WTG010 = 1000.
GS_COSP-WTG011 = 1100.
GS_COSP-WTG012 = 1200.

DATA : FNAME(14). " 필드명을 담을 변수 선언
DATA : SUM LIKE COSP-WTG001. " 합계 금액을 담을 변수 선언

DATA : CC(2) TYPE N. " 필드명 변수 만드는 데 쓰일 변수 선언
DO 12 TIMES.
  CC = SY-INDEX. " 01, 02, 03 ...
  CONCATENATE 'GS_COSP-WTG0' CC INTO FNAME. " WTG001, WTG002, WTG003 ...

  ASSIGN (FNAME) TO <FS>.
  SUM = SUM + <FS>.
  CLEAR : FNAME, <FS>.

  WRITE : / SUM.

ENDDO.

- 위처럼 테이블 구조가 1월 2월 3월 ~ 12월 등 필드가 연속된 날짜 등으로 구분되어 있는 경우

- 필드 심볼을 이용하여 필드명을 동적으로 조작해서 ROW가 아닌 COLUMN을 DO같은 반복문을 이용해 조작할 수가 있다.

 

 

데이터 참조

- 데이터 참조는 데이터 오브젝트에 대한 포인터이다.

- 필드 심볼은 포인터만 가지고 있으며 ASSIGN된 데이터 오브젝트의 메모리에서 작업하지만 데이터 참조는 포인터를 값으로 가지는 참조 변수이며 자신의 메모리 영역을 갖는다.

PARAMETERS : P_TNAME(30) DEFAULT 'SFLIGHT'.

DATA : DREF TYPE REF TO DATA.

FIELD-SYMBOLS : <FS1> TYPE ANY.
FIELD-SYMBOLS : <FS2> TYPE ANY.

CREATE DATA DREF TYPE (P_TNAME). " 데이터 오브젝트 자체를 프로그램 실행 도중 동적으로 생성

ASSIGN DREF->* TO <FS1>.

SELECT *
  FROM (P_TNAME) INTO <FS1> UP TO 3 ROWS.

DO.
  ASSIGN COMPONENT SY-INDEX OF STRUCTURE <FS1> TO <FS2>.
  IF SY-SUBRC NE 0.
    SKIP.
    EXIT.
  ENDIF.

  WRITE : <FS2>.
ENDDO.

ENDSELECT.

- 필드 심볼은 데이터 오브젝트에 담겨 있는 메모리 저장소에 작업을 한다. 필드 심볼은 데이터 오브젝트의 또 다른 상징적인 이름일 뿐이다.

- 데이터 참조(Reference Variable)는 데이터 오브젝트를 가리키는 포인터이며 필드 심볼을 통해 데이터 오브젝트의 값에 접근한다ㅐ. 

- 프로그램 실행 시점에 데이터 오브젝트는 동적으로 생성되기 때문에 메모리 주소도 동적으로 할당된다.

- 이것이 필드 심볼을 이용하여 데이터 오브젝트에 접근하게 되는 이유이다.

 

PARAMETERS : P_TNAME(30) DEFAULT 'SFLIGHT'.

DATA : DREF TYPE REF TO DATA.

FIELD-SYMBOLS : <FS1> TYPE ANY.
FIELD-SYMBOLS : <FS2> TYPE ANY.

CREATE DATA DREF TYPE (P_TNAME). " 데이터 오브젝트 자체를 프로그램 실행 도중 동적으로 생성, 참조 변수가 데이터 오브젝트의 주소값을 가지게 됨.

ASSIGN DREF->* TO <FS1>. " 동적으로 생성된 데이터 오브젝트의 값에 접근할 때 필드 심볼을 이용하기 위해 필드 심볼에 assign(dereference)
" dereference : 주소를 통해 값에 접근하는 것
" DREF는 참조 변수고 메모리 주소를 값으로 가질 뿐 데이터 오브젝트 그 자체는 아니다.
" DREF가 가리키는 메모리 주소를 FS1에게 할당하여 FS1이 데이터 오브젝트를 가리키게 하는 것이 Dereference이다.  
SELECT *
  FROM (P_TNAME) INTO <FS1> UP TO 3 ROWS.

DO.
  ASSIGN COMPONENT SY-INDEX OF STRUCTURE <FS1> TO <FS2>.
  IF SY-SUBRC NE 0.
    SKIP.
    EXIT.
  ENDIF.

  WRITE : <FS2>.
ENDDO.

ENDSELECT.

- DREF가 가리키는 데이터 오브젝트는 메모리 주소이며 FS1에게 이 메모리 주소를 할당하여 FS1이 메모리 주소를 통해 동적으로 생성한 데이터 오브젝트에게 접근하도록 유도한다.

 

- 테이블명 등을 파라미터로 받아와서 사용하는 경우에는 미리 어떤 테이블의 구조체나 인터널 테이블에 맞는 데이터 오브젝트를 생성해 놓을 수 없으므로 동적으로 생성해 그 데이터 오브젝트의 메모리 주소를 data reference에 담아두고 Field Symbol에 할당하여 활용한다.  

 

TYPES : BEGIN OF T_STRUCT,
  COL1 TYPE CHAR15,
  COL2 TYPE CHAR15,
END OF T_STRUCT.

DATA : DREF1 TYPE REF TO DATA. " 참조변수 선언
DATA : DREF2 TYPE REF TO DATA.

FIELD-SYMBOLS : <FS1> TYPE T_STRUCT.
FIELD-SYMBOLS : <FS2> TYPE CHAR15.

CREATE DATA DREF1 TYPE T_STRUCT. " 데이터 오브젝트 생성하고 그 주소값을 참조 변수에 대입

ASSIGN DREF1->* TO <FS1>. " DREF1이 가리키는 메모리 주소로 가서 데이터 오브젝트를 가리키도록 FS1에게 할당

<FS1>-COL1 = 'ENJOY ABAP'.
<FS1>-COL2 = 'ABAP PROGRAMMING'.

DREF2 = DREF1.

ASSIGN DREF2->* TO <FS2> CASTING.
WRITE / <FS2>.

GET REFERENCE OF <FS1>-COL2 INTO DREF2. " 이미 생성된 데이터 오브젝트를 참고하여 참조 변수 생성

ASSIGN DREF2->* TO <FS2>.
WRITE / <FS2>.

 

728x90

'SAP&ABAP > ABAP' 카테고리의 다른 글

(작업중)EASY ABAP - 11. Report Program (With ALV)  (0) 2024.06.10
(작업중)EASY ABAP - 9-1. ABAP Dictionary  (0) 2024.04.24