- 일단 필드 심볼이 할당되면 데이터 오브젝트와 필드 심볼 간에는 차이가 없다(필드 심볼 변경이 곧 데이터 오브젝트 변경)
- MOVE와 같은 ABAP 명령어 사용 가능
- 필드 심볼은 타입을 명시 혹은 명시하지 않고도 생성할 수 있다. 타입이 명시되지 않으면 할당되는 오브젝트의 타입을 그대로 상속받는다.
FIELD SYMBOL 메커니즘(그림)
- 필드 심볼에 할당되면 같은 메모리 주소를 할당받기 때문에 필드 심볼이 곧 해당 데이터 오브젝트를 가리키는 변수가 된다.
- 즉 필드 심볼을 이용하여 변수값을 변경하는 것과 기존 변수명을 이용하여 변수값을 변경하는 것은 차이가 없다.
- ASSIGN을 만나면 아무 것도 가리키고 있지 않은 필드 심볼이라는 포인터가 특정 데이터 오브젝트를 가리키는 포인터가 된다.
DATA : BEGINOFLINE,
COL1(12) VALUE'1234567890AB',
ENDOFLINE.
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>LIKELINEOF 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 : BEGINOF GS_STR,
COL1 TYPE CHAR5 VALUE'KOREA',
COL2 TYPE CHAR10 VALUE'SEOUL',
COL3 TYPE CHAR15 VALUE'TWIN BUILDDING',
ENDOF GS_STR.
" 필드명을 담을 변수 선언
DATA : GV_FNAME TYPE CLENGTH10.
DATA : GV_IDX TYPE N.
FIELD-SYMBOLS : <FS1>LIKE GS_STR. " 구조체 가리킬 필드 심볼
FIELD-SYMBOLS : <FS2> TYPE ANY. " 구조체의 각 필드를 가리킬 필드 심볼
ASSIGN GS_STR TO<FS1>. " 구조체 할당
DO3TIMES.
CLEAR : GV_FNAME.
GV_IDX=SY-INDEX.
GV_FNAME='COL'.
CONCATENATE GV_FNAME GV_IDX INTO GV_FNAME. " 필드명 동적 생성
ASSIGNCOMPONENT GV_FNAME OFSTRUCTURE<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 : BEGINOF GS_LINE,
CARRID TYPE SFLIGHT-CARRID,
CONNID TYPE SFLIGHT-CONNID,
CARRNAME TYPE SCARR-CARRNAME,
ENDOF GS_LINE.
DATA : GT_ITAB LIKE TABLEOF GS_LINE.
FIELD-SYMBOLS : <FS>LIKE GS_LINE.
SELECT CARRID CONNID
INTOCORRESPONDINGFIELDSOF TABLE GT_ITAB
FROM SFLIGHT.
LOOP AT GT_ITAB ASSIGNING<FS>.
SELECTSINGLE CARRNAME INTO<FS>-CARRNAME
FROM SCARR WHERECARRID=<FS>-CARRID.
WRITE : /<FS>.
ENDLOOP.
DATA : BEGINOF GS_LINE,
CARRID TYPE SFLIGHT-CARRID,
CONNID TYPE SFLIGHT-CONNID,
CARRNAME TYPE SCARR-CARRNAME,
ENDOF GS_LINE.
DATA : GT_ITAB LIKE TABLEOF GS_LINE.
FIELD-SYMBOLS : <FS>LIKE GS_LINE.
SELECT CARRID CONNID
INTOCORRESPONDINGFIELDSOF TABLE GT_ITAB
FROM SFLIGHT.
LOOP AT GT_ITAB ASSIGNING<FS>. " 필드 심볼에 할당
SELECTSINGLE CARRNAME INTO<FS>-CARRNAME
FROM SCARR WHERECARRID=<FS>-CARRID.
" 인터널테이블에 그대로 넣고 MODIFY 구문 없이도 인터널 테이블 변경됨
" EX) MODIFY GT_ITAB FROM GS_ITAB <= 이런 구문 없어도 인터널 테이블 변경됨.
WRITE : /<FS>.
ENDLOOP.
필드 심볼 활용
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 : SUMLIKE COSP-WTG001. " 합계 금액을 담을 변수 선언
DATA : CC(2) TYPE N. " 필드명 변수 만드는 데 쓰일 변수 선언
DO12TIMES.
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 TODATA.
FIELD-SYMBOLS : <FS1> TYPE ANY.
FIELD-SYMBOLS : <FS2> TYPE ANY.
CREATEDATA DREF TYPE (P_TNAME). " 데이터 오브젝트 자체를 프로그램 실행 도중 동적으로 생성
ASSIGN DREF->* TO<FS1>.
SELECT*
FROM (P_TNAME) INTO<FS1> UP TO3 ROWS.
DO.
ASSIGNCOMPONENTSY-INDEXOFSTRUCTURE<FS1> TO<FS2>.
IFSY-SUBRCNE0.
SKIP.
EXIT.
ENDIF.
WRITE : <FS2>.
ENDDO.
ENDSELECT.
- 필드 심볼은 데이터 오브젝트에 담겨 있는 메모리 저장소에 작업을 한다. 필드 심볼은 데이터 오브젝트의 또 다른 상징적인 이름일 뿐이다.
- 데이터 참조(Reference Variable)는 데이터 오브젝트를 가리키는 포인터이며 필드 심볼을 통해 데이터 오브젝트의 값에 접근한다ㅐ.
- 프로그램 실행 시점에 데이터 오브젝트는 동적으로 생성되기 때문에 메모리 주소도 동적으로 할당된다.
- 이것이 필드 심볼을 이용하여 데이터 오브젝트에 접근하게 되는 이유이다.
PARAMETERS : P_TNAME(30) DEFAULT'SFLIGHT'.
DATA : DREF TYPE REF TODATA.
FIELD-SYMBOLS : <FS1> TYPE ANY.
FIELD-SYMBOLS : <FS2> TYPE ANY.
CREATEDATA DREF TYPE (P_TNAME). " 데이터 오브젝트 자체를 프로그램 실행 도중 동적으로 생성, 참조 변수가 데이터 오브젝트의 주소값을 가지게 됨.
ASSIGN DREF->* TO<FS1>. " 동적으로 생성된 데이터 오브젝트의 값에 접근할 때 필드 심볼을 이용하기 위해 필드 심볼에 assign(dereference)
" dereference : 주소를 통해 값에 접근하는 것
" DREF는 참조 변수고 메모리 주소를 값으로 가질 뿐 데이터 오브젝트 그 자체는 아니다.
" DREF가 가리키는 메모리 주소를 FS1에게 할당하여 FS1이 데이터 오브젝트를 가리키게 하는 것이 Dereference이다.
SELECT*
FROM (P_TNAME) INTO<FS1> UP TO3 ROWS.
DO.
ASSIGNCOMPONENTSY-INDEXOFSTRUCTURE<FS1> TO<FS2>.
IFSY-SUBRCNE0.
SKIP.
EXIT.
ENDIF.
WRITE : <FS2>.
ENDDO.
ENDSELECT.
- DREF가 가리키는 데이터 오브젝트는 메모리 주소이며 FS1에게 이 메모리 주소를 할당하여 FS1이 메모리 주소를 통해 동적으로 생성한 데이터 오브젝트에게 접근하도록 유도한다.
- 테이블명 등을 파라미터로 받아와서 사용하는 경우에는 미리 어떤 테이블의 구조체나 인터널 테이블에 맞는 데이터 오브젝트를 생성해 놓을 수 없으므로 동적으로 생성해 그 데이터 오브젝트의 메모리 주소를 data reference에 담아두고 Field Symbol에 할당하여 활용한다.
TYPES : BEGINOF T_STRUCT,
COL1 TYPE CHAR15,
COL2 TYPE CHAR15,
ENDOF T_STRUCT.
DATA : DREF1 TYPE REF TODATA. " 참조변수 선언
DATA : DREF2 TYPE REF TODATA.
FIELD-SYMBOLS : <FS1> TYPE T_STRUCT.
FIELD-SYMBOLS : <FS2> TYPE CHAR15.
CREATEDATA 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>.
GETREFERENCEOF<FS1>-COL2 INTO DREF2. " 이미 생성된 데이터 오브젝트를 참고하여 참조 변수 생성