DELETE데이터베이스 테이블에서 행을 삭제할 때 사용

1. 단일 행 삭제

DELETE FROM scarr WHERE carrid = 'AA'.

- carrid가 'AA'인 행을 DB에서 삭제

 

2. 구조체(워크 에어리어) 사용해서 삭제

DATA: gs_scarr TYPE scarr.
gs_scarr-carrid = 'AA'.
DELETE scarr FROM gs_scarr.

 

 

3. 내부 테이블로 여러 행 삭제

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

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

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

DELETE scarr FROM TABLE gt_scarr.

 

 

4. 삭제 후 확인 

SELECT SINGLE * FROM scarr INTO gs_scarr WHERE carrid = 'AA'.
IF sy-subrc <> 0.
  WRITE: / 'AA 항공사 삭제 완료!'.
ELSE.
  WRITE: / 'AA 항공사가 아직 존재함.'.
ENDIF.

 

 

⚠️ 주의할 점

 

  • DELETE scarr. ← 이렇게 조건 없이 쓰면 모든 데이터가 삭제됨 (절대 X)
명령어 설명
DELETE FROM ... WHERE 조건 걸어서 직접 삭제
DELETE ... FROM wa 구조체 값으로 삭제 (키 기준)
DELETE ... FROM TABLE 내부 테이블을 기준으로 여러 행 삭제

'SAP' 카테고리의 다른 글

easy abap 15. 효율적인 SQL 구문 작성  (0) 2025.05.09
easy abap 14. modify  (0) 2025.05.09
easy abap 12. Update  (0) 2025.05.09
easy abap 11. INSERT  (0) 2025.05.09
easy abap 10. select - join & 그 외 문법  (0) 2025.05.09

 

1. UPDATE

UPDATE INTO <target> <lines>.

- 테이블의 하나 또는 여러 line을 변경한다. 

- target은 테이블 이름으로, 동적 선언이 가능하다.

 

UPDATE <dbtab> [CLIENT SPECIFIED] <lines>.

- client지정이 가능하며, 테이블 명을 동적/정적으로 선언 가능하다.

 

 

1. 구조체 하나로 업데이트할 때 (UPDATE ... FROM)

DATA: gs_scarr TYPE scarr,
      gv_carrid TYPE scarr-carrid.

gv_carrid = 'AA'.

gs_scarr-carrid = gv_carrid.
gs_scarr-carrname = 'Updated Airline'.
gs_scarr-url = 'https://updated-airline.com'.

UPDATE scarr FROM gs_scarr.

CLEAR gs_scarr.
SELECT SINGLE * INTO gs_scarr FROM scarr WHERE carrid = gv_carrid.

WRITE: / 'Carrid:', gs_scarr-carrid,
       / 'Carrname:', gs_scarr-carrname,
       / 'URL:', gs_scarr-url.

 

 

2. 필드를 지정해서 업데이트할 때

UPDATE scarr
  SET carrname = 'Korea Airlines', url = 'https://www.koreanairlines.com'
  WHERE carrid = 'KO'.

 

UPDATE scarr SET carrname = 'Korea Airlines', url = 'https://www.airlinekorean.com'
WHERE carrid = 'KO'.

* DB에서 다시 읽어오기
SELECT SINGLE * INTO gs_scarr FROM scarr WHERE carrid = 'KO'.

WRITE: / 'carrid: ', gs_scarr-carrid,
         / 'CARNAME: ', gs_scarr-carrname,
         / 'URL: ', gs_scarr-url.

URL이 바뀐 것을 확인할 수 있다.

db에서 읽어오려면, SELECT 로 DB를 읽어올 수 있다.

- 이렇게 하면 UPDATE가 성공적으로 되는 것을 확인할 수 있다!

 

 

3. 내부 테이블로 여러 행 업데이트 (UPDATE FROM TABLE)

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

" 첫 번째 업데이트 데이터
gs_scarr-carrid   = 'AA'.
gs_scarr-carrname = 'Updated American'.
gs_scarr-url      = 'https://www.updatedaa.com'.
APPEND gs_scarr TO gt_scarr.

" 두 번째 업데이트 데이터
gs_scarr-carrid   = 'AF'.
gs_scarr-carrname = 'Updated France'.
gs_scarr-url      = 'https://www.updatedaf.com'.
APPEND gs_scarr TO gt_scarr.

" 내부 테이블로 업데이트
UPDATE scarr FROM TABLE gt_scarr.

" 확인용 SELECT 출력
CLEAR gs_scarr.
SELECT SINGLE * INTO gs_scarr FROM scarr WHERE carrid = 'AA'.
WRITE: / 'AA ->', gs_scarr-carrname, gs_scarr-url.

SELECT SINGLE * INTO gs_scarr FROM scarr WHERE carrid = 'AF'.
WRITE: / 'AF ->', gs_scarr-carrname, gs_scarr-url.

'SAP' 카테고리의 다른 글

easy abap 14. modify  (0) 2025.05.09
easy abap 13. Delete  (0) 2025.05.09
easy abap 11. INSERT  (0) 2025.05.09
easy abap 10. select - join & 그 외 문법  (0) 2025.05.09
easy abap 09. SELECT  (0) 2025.05.08

1. INSERT 구문

INSERT INTO <target> <lines>.
<f2> [ASCENDING | DESCENDING] ...

- 테이블에 하나 또는 여러 개의 데이터를 삽입하면, <target>은 테이블 이름으로, 동적으로 선언할 수 있다.

 

1) single line

INSERT INTO <target> VALUES <wa>.
INSERT <target> FROM <wa>.
INSERT <dbtab>.

 

첫번째 data의 gs_scarr을 출력한 것은 메모리에 넣은 변수이고, 두번째 data gs_scarr은 db에 있는 scarr의 내용을 select로 확인할 수 있다.

 

2) several lines

- 항공사 운항일정을 저장하는 spfli테이블에 데이터를 추가하고 출력해보았다. 

잘나옴!

하지만 위 출력결과는 DB로 부터 읽어온 결과가 아닌 메모리상 내부테이블을 읽어온것

DB에 있는 내용을 출력하고 싶으면 아래 코드로 컴파일하면 된다.

 

SELECT * INTO TABLE gt_spfli FROM spfli WHERE carrid = 'KO'.
LOOP AT gt_spfli INTO gs_spfli.
  WRITE: / gs_spfli-carrid, gs_spfli-connid, gs_spfli-cityfrom, gs_spfli-cityto.
ENDLOOP.

 

 

INSERT spfli FROM TABLE gt_spfli ACCEPTING DUPLICATE KEYS.

- INSERT는 기본적으로 중복 키가 있으면 RUN TIME ERROR가 발생함 

- 위와 같이 INSERT를 쓰면 중복 키인 행은 건너뛰고, 정상적인 행은 삽입함

 

전체적인 INSERT 구문 종류 정리 

 

1.  INSERT INTO … VALUES

- 한 건(insert one row) 삽입할 때 사용

DATA: gs_scarr TYPE scarr.

gs_scarr-carrid = 'KO'.
gs_scarr-carrname = 'Air Korea'.
gs_scarr-url = 'https://www.airkorea.co.kr/'.

INSERT INTO scarr VALUES gs_scarr.

- VALUES 뒤에 구조체를 넘겨서 한 줄만 삽입

 

 

2.  INSERT … FROM TABLE

- 내부 테이블 전체(insert multiple rows) 삽입할 때 사용

DATA: gt_spfli TYPE TABLE OF spfli.

" gt_spfli에 데이터 채우기...

INSERT spfli FROM TABLE gt_spfli ACCEPTING DUPLICATE KEYS.

 

요약 

구문 용도 특징
INSERT INTO tab VALUES wa 단일 행 삽입 SQL과 유사
INSERT tab FROM TABLE itab 여러 행 삽입 ABAP 전용 구문
INSERT ... ACCEPTING DUPLICATE KEYS 중복 무시하고 삽입 ABAP 고유 기능

 

'SAP' 카테고리의 다른 글

easy abap 13. Delete  (0) 2025.05.09
easy abap 12. Update  (0) 2025.05.09
easy abap 10. select - join & 그 외 문법  (0) 2025.05.09
easy abap 09. SELECT  (0) 2025.05.08
easy abap 08. R/3 Architecture, OPEN SQL  (0) 2025.05.07

1. join구문

종류 설명
INNER JOIN 양쪽 테이블에서 조건을 만족하는 행만 선택
LEFT OUTER JOIN 왼쪽 테이블의 모든 행 + 조건을 만족하는 오른쪽 테이블의 행
RIGHT OUTER JOIN 오른쪽 테이블의 모든 행 + 조건을 만족하는 왼쪽 테이블의 행
FULL JOIN ABAP Open SQL에서는 직접 지원하지 않음

 

- abap 프로그럄에서는 테이블 간의 join을 하기 보다는 인터널 테이블에 데이터를 저장하고, LOOP 구문을 이용해,

추가 정보를 SELECT 하여 인터널 테이블 내용을 MODIFY하는 경우가 많다

2. 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 = b~carrid
 WHERE a~carrid = 'AA'.
 
 WRITE : gs_str-carrid, gs_str-carrname.

출력 => AA American Airlines

- inner join은 a와 b 테이블에서 조건이 있는 공통점들을 추출하는 조인이다.

 

3. Outer join

- Inner join은 두 테이블 모두 일치하는 값이 있어야 결과가 나오지만, Outer join은 한 쪽 테이블에는 데이터가 있고 다른 쪽엔 없어도 결과를 보여준다.

JOIN 종류 설명
INNER JOIN 양쪽 테이블에 모두 존재하는 데이터만 결과로 가져옴
LEFT OUTER JOIN 왼쪽 테이블 기준, 오른쪽이 없어도 왼쪽 데이터는 결과에 포함됨
RIGHT OUTER JOIN 오른쪽 테이블 기준, 왼쪽이 없어도 오른쪽 데이터는 결과에 포함됨

- outer join은 단독으로 쓸 수 없으며 방향을 무조건 지정해야한다(Left or Right).

- 아밥 문법적으로 명확한 방향성이 있어야하기 때문이다. 

 

예를들어,

INSA 테이블은 사원 기본 정보를 저장, CERT 테이블은 사원이 취득한 자격증 벙보를 저장하고 있다고 치자.

사원 Konie와 Wonie는 자격증을 가지고 있지만, 사원 sonie는 자격증이 없다. 사원 번호 필드를 기준으로 Inner join 하게 되면 사원 sonie는 자격증이 없기 떄문에 결과에서 제외된다.

 

기본적으로는 모든 사원 정보는 조회하고, 자격증이 있는 경우만 추가적으로 보여주고자 할 때 OUTER JOIN이 필요하다.

 

 

 

 

1) interval조건

- 조건에 범위 값을 사용할 때 사용한다.

Select ... where <s> [not] BETWEEN <f1> AND <f2>

 

2) String 비교

- 문자열 비교할 떄는 LIKE or '_'문자를 사용한다.

 

COL2 = 'ABCDEFGHIJK'.

SELECT ~ WHERE COL2 LIKE 'ABC%'.

// 4문자 구할 때
WHERE COL2 LIKE 'ABC_'.

 

3) list value

SELECT a~carrid, a~connid, b~carrname
  INTO CORRESPONDING FIELDS OF TABLE @gt_str
  FROM sflight AS a
  LEFT OUTER JOIN scarr AS b
    ON a~carrid = b~carrid
  WHERE a~carrid IN ('AA', 'ZZ').

- List Value : in 구문을 사용해, 여러 조건에 속한 경우의 값을 가져올 수 있다. AA, ZZ 일 경우 whrere in ('aa', 'zz')를 사용할 수 있다.

 

4) selection table 

SELECT-OPTIONS: so_carrid FOR sflight-carrid.

 

이 줄은 -> ABAP이 자동으로 아래와 같은 내부테이블을 만든다.

sign option low high
I EQ AA  
I BT AB AD
I EQ LH  

 

 

5) Dynamic 조건

- select 구문의 조건을 설정하는 where구문을 동적으로 구성할 수 있다. Itab은 최대 72자리의 Internal table로 선언해야한다.

- 그래서 왜 dynamic조건일까? 그냥 where 다음의 조건절을 빼서, 그 변수에다 선언하면 되기 때문이다. 

즉, 문자열로 구성된 조건식을 where절에 직접 넘기기 때문에 다이나믹 이라고 불린다.

 

이 코드에서

CONCATENATE 'carrid = ''' gv_carrid '''' INTO gs_where.

// 결과 : carrid = 'AC'

결과는 carrid = 'AC'로 나온다.

이 문자열을 where (gs_where)에서 조건식처럼 사용할 수 있다.

// 일반적인 정적 조건문 
SELECT SINGLE carrname
  INTO gv_carrname
  FROM scarr
  WHERE carrid = 'AC'.

// 다이나믹 조건문
DATA: gs_where TYPE c LENGTH 72.
WHERE (gs_where).
-> 조건식 자체가 문자열로 되어있고, 실행 시점에 바뀔 수 있다.

- 사용자 입력값이나 설정값에 따라 매번 달라지는 경우

- select-options, parameters를 직접 파싱해서 동적 조건으로 만들고 싶을 때

- 복잡한 검색조건을 조합해서 쿼리에 반영할 때 유용하다.

 

 

- concatenate로 문자열을 이어붙여서 2개 이상의 조건이 필요할 경우, 동적으로 구성이 가능하다.

6) for all entries 

 

SELECT ...
  FROM <table>
  INTO TABLE <result_itab>
  FOR ALL ENTRIES IN <source_itab>
  WHERE <field> = <source_itab>-<field>.
DATA: lt_carrid TYPE TABLE OF sflight,
      lt_scarr  TYPE TABLE OF scarr.

SELECT carrid
  FROM sflight
  INTO TABLE lt_carrid
  WHERE price > 500.

IF lt_carrid IS NOT INITIAL.
  SELECT *
    FROM scarr
    INTO TABLE lt_scarr
    FOR ALL ENTRIES IN lt_carrid
    WHERE carrid = lt_carrid-carrid.
ENDIF.

 

7) GROUPING 

- group by는 SQL 집계 함수(count, sum, max, min)과 함께 데이터를 그룹별로 묶어서 처리할 때 사용하는 구문.

함수 설명
COUNT(*) 행 수를 센다
SUM(필드) 합계를 구한다
MAX(필드) 최대값
MIN(필드) 최소값
AVG(필드) 평균값 (SAP HANA에서만 가능)
STDDEV 표준편차
VARIANCE 분산
SELECT carrid, COUNT(*) AS cnt
  FROM sflight
  INTO TABLE @DATA(result)
  GROUP BY carrid.

LOOP AT result INTO DATA(ls_result).
  WRITE: / 'carrid: ', ls_result-carrid, 'cnt: ', ls_result-cnt.
ENDLOOP.

 

- 이런식으로 grouping을 하면, 각 carrid에 있는 항공사명의 Cnt를 셀 수 있게 된다.

 

- 항공기 ID별 평균 예약 점유율을 SELECT하는 구문을 실습하면, `Unknown column name "AVG"`라고 뜬다.

 

8) HAVING절 

 

- HAVING절로 조건문을 구할 수 있다.

 

7) SORT구문

- ORDER BY PRIMARY KEY

- 테이블의 key에 의해 정렬됨

- SELECT * 구문인 경우에만 사용가능

- JOIN 구문 및 VIEW에는 사용이 불가

 

SORT <internal_table> [BY <field1> [ASCENDING|DESCENDING] <field2> ...].

 

-> 오름차순, 내림차순 정렬을 사용할 수 있다.

 

9) 서브쿼리_sub query

 

  • 메인 쿼리(Main Query) 안에 또 다른 SELECT문을 넣은 것.
  • 결과를 조건값, 필드값, 또는 테이블로 사용하는 방식

스칼라 서브쿼리(Scalar Subquery)란?

  • 하나의 값만 반환하는 서브쿼리.
  • 주로 SELECT, WHERE, HAVING 절 안에서 사용됨.
  •  
SELECT carrid, connid, price
  INTO TABLE @DATA(result)
  FROM sflight
  WHERE price > (
    SELECT AVG( price )
      FROM sflight
  ).

 

✔️ 실습문제 예시

문제: sflight 테이블에서 평균 가격보다 높은 항공편의 carrid, connid, price를 출력하세요.

SELECT carrid, connid, price
  INTO TABLE @DATA(gt_result)
  FROM sflight
  WHERE price > (
    SELECT AVG( price ) FROM sflight
  ).

 

 

EXISTS 서브쿼리

  • **서브쿼리 결과가 존재하는지(true/false)**를 조건으로 확인.
  • 보통 상관 서브쿼리 형태로 많이 씀.
SELECT carrid, connid, price 
INTO TABLE @DATA(gt_exists) 
FROM sflight AS a 
WHERE EXISTS 
( SELECT * FROM scarr AS b WHERE b~carrid = a~carrid AND b~carrname = 'Lufthansa' ).
 

📝 의미: sflight에서 carrid가 Lufthansa인 항공사에 속한 데이터만 가져오기

 

IN 서브쿼리

  • 값이 특정 리스트 안에 있는지 확인할 때 사용
 
SELECT carrid, connid, price 
INTO TABLE @DATA(gt_in) FROM sflight 
WHERE carrid IN ( SELECT carrid FROM scarr WHERE currcode = 'EUR' ).

📝 의미: 유로(EUR) 화폐를 사용하는 항공사들의 항공편만 가져오기

 

종류 특징 예시
IN 여러 값을 비교할 때 carrid가 'LH', 'AA', 'AF' 중 하나
EXISTS 존재 여부만 확인 연결된 데이터가 있는지 확인
스칼라 한 개 값 반환 & 비교 평균보다 큰 값 찾기

 

'SAP' 카테고리의 다른 글

easy abap 12. Update  (0) 2025.05.09
easy abap 11. INSERT  (0) 2025.05.09
easy abap 09. SELECT  (0) 2025.05.08
easy abap 08. R/3 Architecture, OPEN SQL  (0) 2025.05.07
easy abap 07. constants, statics, tables  (0) 2025.05.07

OPEN SQL은 DML만 사용가능하다.

명령어 설명 포인트
SELECT 행 조회 INTO 또는 INTO TABLE 사용
INSERT 새 행 삽입 실패 시 sy-subrc 체크
UPDATE 기존 행 수정 WHERE 조건 필수
MODIFY 삽입 또는 수정 자동 처리 키 유무로 삽입/수정 결정
DELETE 조건에 맞는 행 삭제 WHERE 또는 구조체 가능

 

SELECT - 데이터 조회

순서 설명
1️⃣ SELECT 가져올 필드를 지정 (또는 * 전체)
2️⃣ INTO 데이터를 저장할 대상 (워크 영역 또는 내부 테이블)
3️⃣ FROM 데이터를 가져올 테이블 이름
4️⃣ WHERE 조건절: 필터링 조건 지정
5️⃣ GROUP BY 그룹핑 기준 필드 지정 (집계 함수 사용 시)
6️⃣ HAVING 그룹핑된 결과에 조건 추가
7️⃣ ORDER BY 결과 정렬 기준 필드 지정

- sql구문은 이 순서를 지켜야한다.

- 데이터베이스에서 하나의 라인 값을 읽을 경우에는 SINGLE을 사용한다

`SELECT SINGLE <cols> ... where'

- 여러 라인을 조회할 때는 select 결과가 내부 테이블에 저장되는데, 이를 인터널 테이블이라고 부른다.

Distinct 를 사용하게 되면 중복된 값이 제외된다.

`SELECT [DISTINCT] <cols> ... WHERE`

- INTO구문의 결과가 저장되는 곳이 인터널 테이블이 아닌 필드orWorkArea(구조체)일 때는 마지막에 ENDSELECT를 사용해야한다.

 

 

- gt_itab = 내부테이블

- gs_wa = 워크에어리어_구조체

- 구조체를 출력하는 코드 

- sap 테이블인 sflight는 여러 필드_컬럼을 갖고 있음 => gs_wa는 로컬구조체가 되고, gs_wa-carrid 처럼 개별 필드에 접근할 수 있음

- TYPE sflight을 쓰면, 그 테이블의 행 구조를 그대로 복사하고 데이터는 들어있지 않고 구조만 복사됨

- Select 쓰면 실제 행을 읽어와서 gs_wa에 데이터를 담는 작업이 실행됨

 

 

- g_itab 내부테이블을 출력하는 코드

- DB에서 조건에 맞는 모든 데이터를 한꺼번에 gt_itab에 담고, LOOP AT으로 내부에서 반복함(메모리 반복)

비교

항목 SELECT INTO TABLE  SELECT ... ENDSELECT
데이터 처리 시점 DB에서 모두 가져와서 한꺼번에 메모리로 DB에서 한 줄씩 읽고 바로 처리
반복 방식 LOOP AT 필요 자체 반복 (SELECT-ENDSELECT가 루프 역할)
성능 대량 데이터 시, 메모리 사용 많음 대량 데이터 시, I/O 부담 적음
 

예시 비교 (결과는 같음)

① SELECT INTO TABLE + LOOP

SELECT * FROM sflight INTO TABLE gt_itab WHERE carrid = 'AA'. 
    LOOP AT gt_itab INTO gs_wa. 
    WRITE: / gs_wa-carrid, gs_wa-connid. 
ENDLOOP.

② SELECT ... ENDSELECT

SELECT * FROM sflight INTO gs_wa WHERE carrid = 'AA'. 
    WRITE: / gs_wa-carrid, gs_wa-connid. 
ENDSELECT.

=> 둘 다 "AA"인 항공편들을 같은 순서로 출력하게 됨

 

- as(Alias)

AS구문을 사용해서, 칼럼 명에 병명을 지정할 수 있음

 

gs_line = 'CARRID CONNID'.
SELECT DISTINCT carrid connid INTO TABLE gt_itab FROM sflight.

 

  • gt_itab는 내부 테이블, 여러 줄 데이터를 담는다.
  • gs_wa는 그 내부 테이블의 한 줄과 동일한 구조를 가진 구조체.
  • gs_wa는 오직 하나의 row만 저장할 수 있다.
  • LIKE LINE OF로 선언한 변수는 내부 테이블의 한 줄(row)을 임시로 담는 용도,
    "임시 저장소(temp variable)" 역할

Select intto corresponding fields of <Wa>

SELECT * 
  INTO CORRESPONDING FIELDS OF <워크에어리어> 
  FROM <테이블> 
  WHERE <조건>.

 

- 구조체에 필드가 일부만 포함되어 있을 때

- 또는 필드명이 DB테이블과 완전히 일치할 때 자동으로 매핑시켜줌

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

DATA: gs_short TYPE ty_flight_short.

SELECT * 
  INTO CORRESPONDING FIELDS OF gs_short 
  FROM sflight 
  WHERE carrid = 'AA'.

  WRITE: / gs_short-carrid, gs_short-connid.
  EXIT.
ENDSELECT.

 

② Parameters 

 

 

- Parameters 명령어를 이용하면 사용자가 값을 입력하는 화면_Selection Screen이 조회된다.

- gs_wa-carrid와 gs_wa-connid가 생성된다.

 

GPT와 함께 하는 실습 문제 set.

1.

첫번째 답 

DATA : gs_wa TYPE sflight.
SELECT SINGLE * INTO gs_wa FROM sflight WHERE carrid = 'AA'.
  WRITE: gs_wa-carrid.
ENDSELECT.  "❌ 오류 발생

select문인데 왜 Endselect를 했을 때 오류가 생길까? 

select single 은 단일 행 조회이기 때문에 block이 없기 때문이다. 

data : gs_wa TYPE sflight.

SELECT single * into gs_wa from sflight where carrid EQ 'AA'.

- 이렇게 조회하면 AA의 이름을 가진 carrid가 출력이 된다.

 

2.

DATA : gt_itab TYPE TABLE OF sflight,
	gt_temp TYPE sflight.
SELECT carrid, connid FROM sflight INTO CORRESPONDING FIELDS OF TABLE
	@gt_itab WHERE carrid = 'AA'.
    
LOOP AT gt_itab INTO gt_temp.
	WRITE : / gt_temp-carrid, gt_temp-connid.
ENDLOOP.

 

- 내부테이블에서 LOOP AT <내부테이블> into <작업구조> 형태로 루프를 돌릴 땐, 루프 안에서 한 줄씩 담아줄 작업구조, 즉 워크에어리어가 필요하다.

- `LOOP AT gt_itab ASSIGNING FILED-SYMBOL(<fs>)`처럼 field-symbol을 쓰면 gt_temp가 없어도 된다

 

 

3. 

DATA : gt_itab TYPE TABLE OF sflight,
	gt_temp TYPE sflight.
    
 SELECT carrid, price INTO CORRESPONDING FIELDS OF TABLE
 @gt_itab TYPE sflight
 WHERE carrid = 'AA' AND price >= 300.
 
 LOOP AT gt_itab INTO gt_temp.
 	WRITE : / gt_temp-carrid, gt_temp-price.
 ENDLOOP.

 

- 꼭 @이 필요할까? 

- @은 ABAP 7.40 이후 버전에서 도입된 ABAP new Syntax 때문에 등장함

 

 

 

✅ 다음 문제 (문제 5)

문제 5: SELECT SINGLE + 구조체 + 조건

  • sflight 테이블에서 carrid = 'AA'이고 connid = '0017'인 데이터를 구조체 하나에 담아서,
  • fldate, price, currency 3개 필드를 WRITE로 출력해보세요.

 

- 문제의 조건은 single이였는데, 못보고 그냥 풀어버렸다.

 

 

- single로 푼 문제.

처음에는 `SELECT SINGLE * INTO gt_itab...` 이렇게 풀려고 했으나, 컴파일이 안되는 것을 확인했다.

그 이유는 gt_itab 내부테이블은 여러 개의 행을 저장할 수 있는 자료형이지만, select single은 단 하나의 행만 가져오기 때문에 

구조체 한 개짜리 공간이 필요하기 때문이다.

 

R/3에서 “R”과 “3”의 의미

  • “R” = Real-time (실시간 처리 시스템)
  • “3” = 3-Tier 구조 (Presentation, Application, Database)

🧱 R/3 아키텍처의 3계층 구성

 

계층 설명 예시
1️⃣ Presentation Layer 사용자 인터페이스 (UI) SAP GUI, Fiori 앱
2️⃣ Application Layer 비즈니스 논리 처리 ABAP 프로그램, 함수 모듈 실행
3️⃣ Database Layer 데이터 저장소 Oracle, HANA, MS SQL 등 DBMS

 

1. Presentation Layer (표현 계층)

  • 사용자가 직접 마주하는 부분
  • SAP GUI, 웹 브라우저, 모바일 앱 등
  • 입력한 데이터를 전송하고 결과를 보여줌
  • 💬 사용자 → SAP 서버와의 인터페이스

2. Application Layer (애플리케이션 계층)

  • 핵심 ABAP 프로그램, 트랜잭션, 비즈니스 로직이 실행되는 곳
  • 사용자 요청을 해석하고 처리
  • 워크 프로세스 (Dialog, Update, Batch, Spool 등) 수행
  • 두뇌 역할을 하는 중간 계층

 

3. Database Layer (데이터베이스 계층)

  • 실제 데이터가 저장되는 DBMS
  • 테이블, 인덱스, 트랜잭션 로그 관리
  • SAP는 Oracle, HANA, MSSQL 등 다양한 DBMS와 호환됨
  • 📦 모든 마스터 데이터, 트랜잭션 데이터 저장

💡 작동 흐름 예시

사용자(SAP GUI)
	→ 버튼 클릭 
		→ Application Layer가 로직 실행 
			→ DB에서 데이터 조회 
				→ Application Layer가 처리 후 결과 반환 
					→ 사용자 화면에 결과 표시

 

한눈에 보는 R/3 구조

┌───────────────────────┐
│    Presentation       │  ← SAP GUI / 웹 / 앱
└───────────────────────┘
            ↓
┌───────────────────────┐
│   Application Server  │  ← ABAP 실행, 기능 처리
└───────────────────────┘
            ↓
┌───────────────────────┐
│    Database Server     │  ← 테이블, 인덱스, 로그 저장
└───────────────────────┘

 

- sap는 일반 개발자에게 db에 직접 접속해서 데이터를 수정하는 행위를 금지한다.

- db에 접속하여 데이터를 조회하는 권한도 부여하지 않는다 => 무결성, 일관성, 안정성, 투명성 보장

ABAP개발자는 ABAP Dictionary를 통해 데이터베이스 구조(스키마)를 관리한다.

* abap dictionary : Table, View, Structure, Types등

이러한 오브젝트 정보를 Metadata, Data definition or schema로 정의하며 데이터 구조를 정의하고 관리하는 역할을 ABAP Dictionary가 하게 된다.

 

Open SQL vs Native SQL

 

1. Open SQL

ABAP에서 SAP 시스템에 독립적인 방식으로 데이터베이스를 접근하는 SAP 전용 SQL 언어

특징


항목 설명
SAP DB 독립적 어떤 DB를 쓰든지 동일한 문법으로 사용 가능
보안 및 무결성 보장 SAP에서 필터링 및 권한 검사 수행
ABAP 통합 SELECT, INSERT, UPDATE, DELETE 등 ABAP 문법과 자연스럽게 통합
Buffer 사용 SAP 테이블 버퍼 활용 가능 (성능 향상)
 

예시

SELECT * FROM zemployee INTO TABLE @DATA(lt_emp) WHERE age > 25.

- ddl, dcl 사용 X

- select와 같은 DML만 사용 가능함 

- local buffer사용가능!

 


2. Native SQL

DBMS에 종속적인 SQL 문장을 직접 사용해서 데이터에 접근하는 방식

특징


항목 설명
DBMS 종속 사용하는 DB가 Oracle인지 HANA인지에 따라 문법 다름
SAP 무관 SAP가 SQL 구문을 해석하지 않음 → 그대로 DB로 전송
SAP 버퍼 무시 테이블 버퍼를 사용하지 않음
강력한 제어 가능 복잡한 SQL (JOIN, 서브쿼리 등) 가능, 그러나 위험도 있음
 

예시

 
EXEC SQL. SELECT * FROM zemployee WHERE age > 25 ENDEXEC.

- db에 접속해서 dml, ddl언어도 사용 가능.

- open SQL이 해결이 되지 않는 복잡한 SQL은 NATIVE SQL 이용 가능함.

 

SQL 실행 순서

 

SELECT * FROM marc WHERE werks = '1101'.
	IF sy-subrc EQ 0.
    	WRITE marc.
        EXIT.
    ENDIF.
ENDSELECT.

 

1. Marc테이블에서 werks='1101'인 데이터를 조회하는 SQL을 실행한다.

2. DB interface에서 Native SQL로 해석하여 테이블 MARC에서 WERKS필드가 1101인 값을 가져온다.

3. marc 테이블에는 werks='1101'인 row는 3건이며 해당 데이터는 Local Buffer에 저장된다.

4. SQL의 sy-subrc EQ0. 에서 Db에서 값을 가져오는 구문이 성공하면 exit해서 1101의 첫번째 값이 display된다.

5. 해당 SQL을 실행하면, local buffer에서 werks = '1101'인 데이터가 존재하기 때문에 db에 접근하지 않고 바로 local buffer의 데이터를 반환함.

 

 

1. Constants는 일반 상수와 구조체 상수 2가지 타입을 사용할 수 있다.

 

상수라서 이렇게 write하면 `Easy abap kondi korea`가 출력된다.

 

2. statics 

 

변수 static lv_var.

lv_var에는 0이 초기화되어 있기 때문에 1만큼 계속 추가된다.

static var : 1 

static var : 2

staric var : 3

 

이런식으로 결과가 출력됨 

DO 3 TIMES.
  PERFORM call_subr.
ENDDO.

FORM call_subr.
  DATA lv_val TYPE i.
  lv_val = lv_val + 1.
  WRITE: / 'Local var:', lv_val.
ENDFORM.

하지만 이렇게 되어있으면, 변수가 form을 돌 때마다 초기화된다.

만약에 값을 추가하는 값으로 바꾸고 싶다면, form문 밖에 DATA 를 선언하던지, static으로 선언하면 된다.

 

DATA gv_val TYPE i.

DO 3 TIMES.
  PERFORM call_subr.
ENDDO.

FORM call_subr.
  gv_val = gv_val + 1.
  WRITE: / 'Global var:', gv_val.
ENDFORM.

 

 

3. tables 

tables 구문을 사용해서 abap dictionary, table, view, structure을 선언하면 Abap dictionary와 같은 Data object를 생성하게 된다.

table work area라고 불리며, 프로그램 내에서 구조체처럼 사용가능하다.

 

 

 

1. abap dictionary table, view

 

2. structure을 이용한 type선언 (se11에서 생성한 zstruct)

 

결과 => 1 (개행) Structure Abap dictionary (개행) test 

 

3. move & move-corresponding 사용/ offset 이용한 할당 

 

결과 ABCDEFGH

CDE

CDEF

4. 구조체의 산술연산

 

move-corresponding 구문을 통해 구조체 간의 필드값을 할당할 수 있는 것과 같이 구조체간 연산이 가능함!

 

'SAP' 카테고리의 다른 글

easy abap 08. R/3 Architecture, OPEN SQL  (0) 2025.05.07
easy abap 07. constants, statics, tables  (0) 2025.05.07
easy abap 05.구조체 structure타입 선언  (0) 2025.05.07
easy abap 04. string 함수  (0) 2025.05.07
easy abap 03. string vs c  (0) 2025.05.07

 

1. structure type 선언

 

abap의 구조체는 c의 구조체와 비슷하다.

변수들의 모음집. 구조체가 student라고 한다면, 학생의 객체의 정보를 가지고 있다. 

c도 매 학생마다 구조체를 할당하는 것처럼, abap의 구조체도 학생 변수를 구조체로 정의하고 값을 할당받는다.

이 때, address에 대한 nested구조체를 쓸 수 있다.

 

2. nested 구조체 type 선언

- include type - 키워드를 통해서 nested structure을 사용할 수 있다.

위와 같이 쓰면 된다. 

String에 있는 함수

함수 기능 예시
FIND 문자열 찾기 FIND 'ABAP' IN lv_text.
REPLACE 문자열 바꾸기 REPLACE 'A' WITH 'B' INTO lv.
TRANSLATE 대소문자 변환 TRANSLATE lv TO LOWER CASE.
SHIFT 왼쪽/오른쪽 밀기 SHIFT lv LEFT DELETING LEADING space.
CONDENSE 공백 줄이기 CONDENSE lv.
OVERLAY 문자 덮어쓰기 OVERLAY lv WITH '***'.
CONCATENATE 연결 CONCATENATE a b INTO c.
SPLIT 나누기 SPLIT lv AT ',' INTO x y.

 

 

1. FIND – 문자열 찾기

- 문자열 안에 특정 단어가 존재하는지 확인

기본 문법

FIND '찾을문자' IN lv_text.

예제

DATA : gv_str type string,
	gv_chr(4) type c.
    
    gv_str = 'ABAP'.
    gv_chr = 'B'.
    
    find gv_chr in gv_str.
    if st_subrc eq 0.
    	write 'B FOUND'.
    endif.

=> B FOUND 출력!

위치를 알고 싶을 때 / 기본 문법

FIND 'abap' IN lv_text match offset lv_pos.

 

예제

DATA: lv_text TYPE string VALUE 'I love ABAP programming.',
      lv_pos  TYPE i.

FIND 'ABAP' IN lv_text MATCH OFFSET lv_pos.

WRITE: / 'ABAP 위치:', lv_pos.

결과 : ABAP 위치 : 7 (7번째 인덱스부터 시작)

 

2. REPLACE – 문자열 교체

문자열 안의 특정 단어를 다른 단어로 바꿈

기본 문법

 
REPLACE '기존문자' WITH '새문자' INTO lv_text.

예시

DATA lv_text TYPE string VALUE 'I love ABAP!'.
REPLACE 'love' WITH 'like' INTO lv_text.
WRITE: / lv_text. " 결과: I like ABAP!

예시2.

gv_str = 'ABAP'.
gc_chr = 'BBAP'.
REPLACE 'ABAP' WITH gv_chr INTO gv_str.
WRITE / gv_str.

=> 결과 : BBAP 

 

 

3. TRANSLATE – 대소문자 변환

대문자 ↔ 소문자 변환

문법

 
TRANSLATE lv_text TO UPPER CASE. " 대문자 
TRANSLATE lv_text TO LOWER CASE. " 소문자
 
예시

 

 
DATA lv_text TYPE string VALUE 'abap is great'. 
TRANSLATE lv_text TO UPPER CASE. 
WRITE: / lv_text. " 결과: ABAP IS GREAT

 

 

4. SHIFT – 문자 밀기

문자열을 왼쪽/오른쪽으로 밀면서 공백 제거 가능

 

문법

SHIFT lv_text LEFT DELETING LEADING space.
 

예시

 
DATA lv_text TYPE string VALUE ' ABAP!    '.
SHIFT lv_text LEFT DELETING LEADING space.
WRITE: / lv_text. " 결과: 'ABAP!    '

 

예시2 기본 shift 문법 (왼쪽이동)

gv_str = 'ABAP'.
SHIFT gv_str.
WRITE / gv_str.  " 결과 'BAP'

- 기본으로 shift문법은 왼쪽으로 이동이다. 

구문 설명
SHIFT lv LEFT 왼쪽으로 한 글자 밀기 (기본)
SHIFT lv RIGHT 오른쪽으로 한 글자 밀기
SHIFT lv LEFT DELETING LEADING space 앞쪽 공백 전부 제거
SHIFT lv RIGHT CIRCULAR 순환 이동 (맨 끝 글자가 앞으로 옴)

 

예시: 순환 이동

DATA lv TYPE string VALUE 'ABAP'. 
SHIFT lv RIGHT CIRCULAR. 
WRITE: / lv. " 결과: PABA

 

5. CONDENSE – 공백 압축

여러 공백을 하나로 줄이기, 양끝 공백도 제거 가능

문법

CONDENSE lv_text. " 기본: 중간 공백 압축 + 앞뒤 제거
CONDENSE lv_text NO-GAPS. " 모든 공백 제거
 

예시

DATA lv_text TYPE string VALUE ' ABAP IS FUN '.
CONDENSE lv_text.
WRITE: / lv_text. " 결과: 'ABAP IS FUN'
 

=> 중간 공백 압축 + 앞 뒤 제거가 된다.

=> `condense lv_tex2 no-gaps1` 하면 공백이 다 제거된다.

 

6. OVERLAY – 문자 겹쳐쓰기

기존 문자열을 다른 문자로 덮어쓰기

문법

OVERLAY lv_target WITH '****'.
예시

 

DATA lv_text TYPE string VALUE 'ABAP'.
OVERLAY lv_text WITH '####'.
WRITE: / lv_text. " 결과: ####
gv_str = '  B .    p  '.
gv_chr = 'AAAA'.
overlay gv_str with gv_chr.
write / gv_str.

 

7. CONCATENATE – 문자열 연결

여러 문자열을 하나로 합침

문법

CONCATENATE lv1 lv2 INTO lv_result [SEPARATED BY space].
 

예시

 
DATA: lv1 TYPE string VALUE 'Hello', lv2 TYPE string VALUE 'World', lv_result TYPE string.
CONCATENATE lv1 lv2 INTO lv_result SEPARATED BY space.
WRITE: / lv_result. " 결과: Hello World

gv_str 변수에 gv_chr를 합친다.

 

8. SPLIT – 문자열 나누기

구분자를 기준으로 문자열 분해

문법

SPLIT lv_text AT ',' INTO lv_a lv_b.
 

예시

DATA: lv_text TYPE string VALUE 'ABAP,PROGRAMMING', lv_a TYPE string, lv_b TYPE string.
SPLIT lv_text AT ',' INTO lv_a lv_b.
WRITE: / lv_a, / lv_b. " 결과: ABAP / PROGRAMMING

 

 

 

* 연습하기*

'Hello_World_42' → 'Hello', 'World', '42'로 나누고,
숫자 부분은 숫자로 바꿔서 2 더한 결과 출력하기

data lv_str type string value 'Hello_world_42', lv_a type string, lv_b type string, lv_c type i.
split lv_str at '_' into lv_a lv_b lv_c.
lv_c = lv_c + 2.
write / lv_c.

=> welcome to abap world 만들기

DATA lv_text TYPE string VALUE '##HELLO_world42##'.

REPLACE ALL OCCURRENCES OF '##' IN lv_text WITH ''.
REPLACE ALL OCCURRENCES OF '_' IN lv_text WITH ' '.
REPLACE ALL OCCURRENCES OF REGEX '[0-9]' IN lv_text WITH ''.
TRANSLATE lv_text TO LOWER CASE.
CONDENSE lv_text.

WRITE: / lv_text.  " 결과: hello world

 

 

출력 => hello world ####

+ Recent posts