Database Access

📘 SQL의 서브 랭귀지와 ABAP 프로그램에서 SQL 접근 방법
✅ 1. SQL 서브 랭귀지(Sub-Languages) 세 가지
SQL(Structured Query Language)는 크게 세 가지 서브 랭귀지로 나뉜다.
| Sub-Language | 설명 |
| 데이터 정의 언어 (DDL) | 테이블 생성, 수정, 삭제 등의 테이블 구조 정의 |
| 데이터 조작 언어 (DML) | 데이터 조회, 삽입, 수정, 삭제 등의 데이터 조작 |
| 데이터 제어 언어 (DCL) | 권한 부여, 회수 등의 데이터 접근 제어 |
💡 정리:
- DDL (Data Definition Language): 테이블 생성/수정/삭제
- DML (Data Manipulation Language): 데이터 조작 (INSERT, UPDATE, DELETE, SELECT)
- DCL (Data Control Language): 권한 관리 (GRANT, REVOKE)
✅ 2. ABAP 프로그램에서 SQL을 Access하는 방법
ABAP에서는 데이터베이스에 접근하기 위해 두 가지 SQL 방법을 사용할 수 있다.
| SQL | 설명 | 사용빈도 |
| Native SQL | SQL 구문을 그대로 사용하여 데이터베이스에 직접 접근 | 거의 사용하지 않음 |
| Open SQL | ABAP에 최적화된 SQL 구문을 사용하여 데이터 접근 | 대부분 사용 |
✅ 3. Native SQL vs Open SQL 차이점
| 특징 | Native SQL | Open SQL |
| 사용 구문 | 데이터베이스 종속적 SQL 구문 사용 | 데이터베이스와 무관한 표준 SQL 사용 |
| 데이터베이스 종속성 | 종속적 (DBMS에 따라 다름) | 독립적 (모든 DBMS에서 동일) |
| ABAP 통합 여부 | ABAP 구문과 통합되지 않음 | ABAP 구문과 통합됨 |
| 사용 빈도 | 거의 사용하지 않음 | 대부분 사용 |
💡 정리:
- Native SQL은 특정 데이터베이스(DBMS)에 종속되며, 특별한 경우가 아니면 사용하지 않는다.
- Open SQL은 ABAP 프로그램에서 주로 사용하는 방식이며, 데이터베이스 인터페이스를 통해 데이터베이스 독립적으로 동작한다.
✅ 4. Open SQL의 동작 방식: 테이블 버퍼(Table Buffer)
- Open SQL을 사용할 때, ABAP 서버는 데이터베이스 인터페이스를 통해 데이터를 조회한다.
- ABAP 서버에는 테이블 버퍼(Table Buffer)가 있어서, 데이터를 버퍼에 저장한 후 빠르게 조회할 수 있다.
💡 테이블 버퍼 특징:
- 테이블 버퍼는 메모리 내에 저장된 캐시(Cache) 역할을 한다.
- 테이블 버퍼를 사용하면 데이터베이스에 직접 접근하지 않고,버퍼에 저장된 데이터를 사용해 성능을 향상시킬 수 있다.
- 하지만 테이블 버퍼 사용 여부는 옵션이다.
✅ 5. 예시 코드: Open SQL 사용
📍 Open SQL 사용 예시: 데이터 조회
SELECT * FROM zflight
INTO TABLE it_flight
WHERE carrid = 'AA'.
📍 Open SQL 사용 예시: 데이터 삽입
INSERT INTO zflight
VALUES ('AA', '0017', '2025-01-01').
📍 Open SQL 사용 예시: 데이터 수정
UPDATE zflight
SET price = 600
WHERE carrid = 'AA' AND connid = '0017'.
✅ 6. 핵심 요약
1️⃣ SQL 서브 랭귀지는 DDL, DML, DCL 세 가지로 나뉜다.
2️⃣ ABAP 프로그램에서 SQL 접근 방법은 Native SQL과 Open SQL 두 가지가 있다.
3️⃣ Open SQL은 ABAP 프로그램에서 대부분 사용되며, 데이터베이스 독립적이다.
4️⃣ ABAP 서버에는 테이블 버퍼(Table Buffer)가 있어서, 데이터를 버퍼에서 조회할 수 있으며, 버퍼 사용 여부는 옵션이다.
5️⃣ Native SQL은 특별한 경우에만 사용하며, 일반적으로는 Open SQL을 사용한다.
📘 Open SQL을 통해 데이터를 불러오는 방법: Database Read
✅ 1. Open SQL을 사용한 데이터 조회 기본 구문
데이터베이스에서 데이터를 Open SQL로 조회할 때 사용하는 구문은 다음과 같다:
SELECT * FROM <테이블명>
INTO <변수>
WHERE <조건>.
✅ 2. 구문 구성 설명
| 구문 | 설명 | 필수여부 |
| SELECT | 데이터를 조회하는 SQL 명령어 | ✅ 필수 |
| FROM | 데이터를 가져올 데이터베이스 테이블을 지정 | ✅ 필수 |
| INTO | 데이터를 저장할 변수(Internal Table 또는 Work Area) | ✅ 필수 |
| WHERE | 데이터를 조회할 때 사용할 조건 | ❌ 선택 |
✅ 3. INTO 뒤에는 변수가 와야 한다
- INTO 구문 뒤에는 반드시 데이터를 저장할 변수가 와야 한다.
- 변수는 Internal Table 또는 Work Area일 수 있다.
➡️ 예시: Internal Table에 데이터 저장
SELECT * FROM zflight
INTO TABLE it_flight.
➡️ 예시: Work Area에 데이터 저장
SELECT * FROM zflight
INTO gs_flight.
✅ 4. WHERE 조건 사용 여부
- WHERE 구문은 선택적이다.
- WHERE 조건을 사용하지 않으면 테이블의 모든 데이터를 가져온다.
- WHERE 조건을 사용하면 조건에 맞는 데이터만 조회된다.
➡️ 예시: WHERE 조건 없이 조회 (모든 데이터 조회)
SELECT * FROM zflight
INTO TABLE it_flight.
➡️ 예시: WHERE 조건을 사용하여 조회 (조건에 맞는 데이터만 조회)
SELECT * FROM zflight
INTO TABLE it_flight
WHERE carrid = 'AA'.
✅ 5. FROM과 INTO의 순서는 바꿔도 된다
- Open SQL에서는 FROM과 INTO의 순서를 바꿔도 동일하게 작동한다.
➡️ 예시: FROM과 INTO 순서 변경
SELECT * INTO TABLE it_flight
FROM zflight
WHERE carrid = 'AA'.
✅ 6. 예시 코드: 다양한 데이터 조회 방법
📍 1) 모든 데이터 조회
SELECT * FROM zflight
INTO TABLE it_flight.
📍 2) 조건에 맞는 데이터 조회 (WHERE 사용)
SELECT * FROM zflight
INTO TABLE it_flight
WHERE carrid = 'AA'.
📍 3) Work Area에 한 건의 데이터 조회
SELECT * FROM zflight
INTO gs_flight
WHERE carrid = 'AA' AND connid = '0017'.
✅ 7. 핵심 요약
1️⃣ INTO 뒤에는 데이터를 저장할 변수(Internal Table 또는 Work Area)가 반드시 와야 한다.
2️⃣ WHERE 조건은 선택적으로 사용할 수 있으며,
- 조건이 없으면 테이블의 모든 데이터를 조회하고,
- 조건이 있으면 조건에 맞는 데이터만 조회한다.
3️⃣ FROM과 INTO의 순서는 바꿔도 된다.
4️⃣ Open SQL을 통해 데이터 조회 시,
- Internal Table에 여러 건의 데이터를 저장하거나,
- Work Area에 한 건의 데이터를 저장할 수 있다.

📘 Retrieval of a Single Record: SELECT SINGLE
✅ 1. SELECT SINGLE을 사용하는 이유
- 데이터베이스에서 한 건의 데이터를 가져오기 위해 SELECT SINGLE 구문을 사용한다.
- SELECT SINGLE은 조건에 맞는 첫 번째 레코드를 가져온다.
- 다중 레코드 조회가 아닌, 단일 레코드 조회 시 효율적이다.
✅ 2. SELECT SINGLE 구문 설명
| 구문 | 설명 |
| SELECT SINGLE | 조건에 맞는 첫 번째 레코드를 가져온다 |
| * | 모든 필드를 의미 |
| FROM | 데이터를 가져올 테이블 이름을 지정 |
| INTO | 가져온 데이터를 저장할 Structure Variable |
| WHERE | 조회 조건을 설정하여 특정 데이터를 필터링 |
✅ 3. 구문 구조
SELECT SINGLE *
FROM <테이블 이름>
INTO <Structure Variable>
WHERE <필드 이름> = <조건>.
✅ 4. 예시 코드: SCARR 테이블에서 한 건의 데이터 조회
📍 예시 1: 특정 항공사 코드(CARRID)를 기준으로 한 건의 데이터 조회
DATA: gs_scarr TYPE scarr.
SELECT SINGLE *
FROM scarr
INTO gs_scarr
WHERE carrid = 'AA'.
➡️ 설명:
- SCARR 테이블에서 항공사 코드(CARRID)가 'AA'인 첫 번째 데이터를 gs_scarr에 저장한다.
📍 예시 2: 특정 조건을 변경하여 조회
SELECT SINGLE *
FROM scarr
INTO gs_scarr
WHERE carrid = 'LH'.
➡️ 설명:
- SCARR 테이블에서 항공사 코드(CARRID)가 'LH'인 첫 번째 데이터를 gs_scarr에 저장한다.
✅ 5. 필드별로 조회하기 (SELECT SINGLE + 특정 필드)
📍 예시: 특정 필드만 조회
SELECT SINGLE carrid, carrname
FROM scarr
INTO (gs_scarr-carrid, gs_scarr-carrname)
WHERE carrid = 'AA'.
➡️ 설명:
- 특정 필드인 CARRID*와 CARRNAME만 조회하여 Structure Variable에 저장한다.
✅ 6. 핵심 요약
1️⃣ SELECT SINGLE은 한 건의 데이터를 가져오기 위해 사용한다.
2️⃣ * (아스타)는 테이블의 모든 필드를 의미하며, 특정 필드만 가져올 수도 있다.
3️⃣ FROM 다음에 테이블 이름을 지정하고, INTO 다음에 데이터를 저장할 Structure Variable을 지정한다.
4️⃣ WHERE 구문을 사용하여 조건에 맞는 데이터를 필터링할 수 있다.
5️⃣ SELECT SINGLE은 조건에 맞는 첫 번째 레코드만 가져온다.
💡 전체 예시 코드
DATA: gs_scarr TYPE scarr.
" 한 건의 데이터 조회 (모든 필드 조회)
SELECT SINGLE *
FROM scarr
INTO gs_scarr
WHERE carrid = 'AA'.
" 특정 필드만 조회
SELECT SINGLE carrid, carrname
FROM scarr
INTO (gs_scarr-carrid, gs_scarr-carrname)
WHERE carrid = 'LH'.
📘 INTO 절 배열법: Corresponding Target Structure for the Field List
✅ 1. 필드 리스트로 특정 필드만 조회하기 (SELECT ... INTO)
- SELECT 구문에서 대신 특정 필드만 조회할 수 있다.
- 이때 INTO 절을 사용할 때, 조회된 필드의 순서에 따라 Work Area에 왼쪽부터 순서대로 할당된다.
➡️ 예시:
SELECT carrid, carrname, currcode, url, cityfrom
FROM scarr
INTO (gs_scarr-carrid, gs_scarr-carrname, gs_scarr-currcode, gs_scarr-url, gs_scarr-cityfrom)
WHERE carrid = 'AA'.
✅ 2. INTO 절 배열법의 주의사항
- 조회된 필드 순서와 Work Area의 필드 순서가 일치하지 않거나,
- Work Area 필드의 길이가 테이블 필드의 길이보다 짧을 경우,데이터 할당 시 문제가 발생할 수 있다.
💡 문제 상황:
- 할당된 필드 값이 너무 길면 문자열이 잘리거나
- 잘못된 필드에 값이 들어가면서 프로그램이 덤프 오류를 발생시킬 수 있다.
✅ 3. 해결 방법: CORRESPONDING 사용하기
- CORRESPONDING 구문을 사용하면 필드 이름을 기준으로 데이터를 할당할 수 있다.
- 필드 순서와 필드 길이가 일치하지 않아도 정확한 필드에 값이 할당된다.
➡️ 구문:
SELECT carrid, carrname, currcode, url, cityfrom
FROM scarr
INTO CORRESPONDING FIELDS OF gs_scarr
WHERE carrid = 'AA'.
💡 CORRESPONDING 사용 시 장점:
- 필드 순서와 무관하게 필드 이름을 기준으로 값이 할당된다.
- 데이터 길이 초과로 인한 잘림 현상이 줄어든다.
- 프로그램이 덤프 오류를 발생시킬 가능성이 낮아진다.
✅ 4. 핵심 요약
| 구문 | 설명 | 장점 |
| INTO ( ... ) | 필드 순서에 따라 왼쪽부터 순서대로 할당 | 간단하지만 오류 발생 가능성 있음 |
| INTO CORRESPONDING FIELDS OF | 필드 이름을 기준으로 정확하게 할당 | 오류 발생 가능성 낮음 |
1️⃣ INTO 절을 사용할 때는 필드 순서와 필드 길이를 주의해야 한다.
2️⃣ 필드 순서가 중요하지 않게 데이터를 할당하려면 CORRESPONDING FIELDS OF를 사용하는 것이 좋다.
3️⃣ CORRESPONDING을 사용하면 필드 이름을 기준으로 데이터가 정확하게 할당되므로 덤프 오류를 줄일 수 있다.
📘 Retrieving Multiple Database Records: 다수의 데이터 조회 및 처리
✅ 1. 다수의 데이터 조회 시 반복 처리 필요
- 데이터베이스에서 N건의 데이터를 조회할 때, 조회된 데이터를 반복적으로 처리해야 한다.
- SELECT ... ENDSELECT 구문을 사용하면, 조건에 맞는 다수의 레코드를 순차적으로 Work Area에 할당하여 반복 처리할 수 있다.
✅ 2. SELECT ... ENDSELECT 구문 설명
| 구문 | 설명 |
| SELECT | 데이터 조회를 시작하는 구문 |
| ENDSELECT | 반복 처리의 끝을 나타내는 구문 |
| INTO | 조회된 데이터를 저장할 Work Area를 지정 |
| WHERE | 조건을 설정하여 특정 데이터를 필터링 |
💡 중요:
- 조회된 각 레코드는 SELECT ... ENDSELECT 반복문 안에서 순차적으로 Work Area에 할당된다.
- 반복문 안에서 데이터 처리 로직을 작성해야 한다.
✅ 3. 구문 구조
SELECT *
FROM <테이블 이름>
INTO <Work Area>
WHERE <조건>.
" 반복 처리 로직 작성
WRITE: / <Work Area 필드>.
ENDSELECT.
✅ 4. 예시 코드: 다수의 데이터 조회 및 출력
📍 예시 1: 모든 데이터를 조회하여 출력
DATA: gs_scarr TYPE scarr.
SELECT *
FROM scarr
INTO gs_scarr.
" 조회된 데이터 출력
WRITE: / gs_scarr-carrid, gs_scarr-carrname.
ENDSELECT.
➡️ 설명:
- SCARR 테이블의 모든 데이터를 조회하고, ENDSELECT 반복문 안에서 각 레코드를 출력한다.
📍 예시 2: 조건에 맞는 데이터만 조회하여 출력
DATA: gs_scarr TYPE scarr.
SELECT *
FROM scarr
INTO gs_scarr
WHERE carrid = 'AA'.
" 조회된 데이터 출력
WRITE: / gs_scarr-carrid, gs_scarr-carrname.
ENDSELECT.
➡️ 설명:
- SCARR 테이블에서 CARRID가 'AA'인 데이터만 조회하고 출력한다.

✅ 5. 주의사항: ENDSELECT 전에 데이터 처리 로직 작성
- 데이터 처리 로직은 반드시 ENDSELECT 전에 작성해야 한다.
- SELECT ... ENDSELECT 구문 안에서 반복 처리 로직을 작성하지 않으면, 조회된 데이터가 처리되지 않는다.
❌ 잘못된 예시:
SELECT *
FROM scarr
INTO gs_scarr.
ENDSELECT.
WRITE: / gs_scarr-carrid, gs_scarr-carrname. " 잘못된 위치
✅ 올바른 예시:
SELECT *
FROM scarr
INTO gs_scarr.
WRITE: / gs_scarr-carrid, gs_scarr-carrname. " ENDSELECT 전에 처리 로직 작성
ENDSELECT.
✅ 6. 핵심 요약
1️⃣ SELECT ... ENDSELECT 구문을 사용하면 다수의 데이터(N건)를 반복적으로 처리할 수 있다.
2️⃣ 조회된 데이터는 Work Area에 순차적으로 할당되며, 반복문 안에서 처리 로직을 작성해야 한다.
3️⃣ ENDSELECT 전에 데이터 처리 로직을 작성하지 않으면, 조회된 데이터가 처리되지 않는다.
4️⃣ 조건부 조회를 할 때는 WHERE 구문을 사용하여 필터링할 수 있다.
💡 전체 예시 코드
DATA: gs_scarr TYPE scarr.
SELECT *
FROM scarr
INTO gs_scarr
WHERE carrid = 'AA'.
WRITE: / gs_scarr-carrid, gs_scarr-carrname.
ENDSELECT.
📘 ENDSELECT가 오지 않는 상황: SELECT SINGLE과 SELECT INTO CORRESPONDING FIELDS OF TABLE
✅ 1. ENDSELECT가 오지 않는 이유
ENDSELECT는 SELECT ... ENDSELECT 구문에서 반복적으로 데이터를 처리할 때 사용된다.
하지만 특정 경우에는 ENDSELECT가 필요하지 않다.
➡️ ENDSELECT가 필요 없는 경우:
1️⃣ SELECT SINGLE → 한 건의 데이터만 조회할 때
2️⃣ SELECT INTO CORRESPONDING FIELDS OF TABLE
→ 여러 건의 데이터를 Internal Table에 한 번에 할당할 때
✅ 2. SELECT SINGLE 구문
- SELECT SINGLE은 조건에 맞는 한 건의 데이터만 조회한다.
- 한 건의 데이터만 가져오므로 반복문이 필요 없으며, ENDSELECT를 사용하지 않는다.
➡️ 예시: SELECT SINGLE
DATA: gs_scarr TYPE scarr.
SELECT SINGLE *
FROM scarr
INTO gs_scarr
WHERE carrid = 'AA'.
WRITE: / gs_scarr-carrid, gs_scarr-carrname.
✅ 특징:
- SELECT SINGLE은 조건에 맞는 첫 번째 레코드만 가져온다.
- ENDSELECT가 필요하지 않다.
✅ 3. SELECT INTO CORRESPONDING FIELDS OF TABLE 구문
- SELECT INTO CORRESPONDING FIELDS OF TABLE은 다수의 데이터를 한 번에 Internal Table에 할당한다.
- 데이터를 Internal Table에 바로 저장하기 때문에 반복문이 필요하지 않다.
- 필드 이름을 기준으로 데이터를 할당하므로 필드 순서에 의한 오류를 방지할 수 있다.
➡️ 예시: SELECT INTO CORRESPONDING FIELDS OF TABLE
DATA: it_scarr TYPE STANDARD TABLE OF scarr.
SELECT carrid, carrname, currcode
FROM scarr
INTO CORRESPONDING FIELDS OF TABLE it_scarr.
LOOP AT it_scarr INTO DATA(gs_scarr).
WRITE: / gs_scarr-carrid, gs_scarr-carrname, gs_scarr-currcode.
ENDLOOP.
✅ 특징:
- 데이터를 Internal Table에 한 번에 할당한다.
- ENDSELECT가 필요하지 않다.
- 필드 이름을 기준으로 데이터를 할당하므로 필드 순서 문제를 방지한다.
✅ 4. 두 구문의 차이점
| 구문 | 설명 | ENDSELECT 필요 여부 |
| SELECT SINGLE | 조건에 맞는 한 건의 데이터 조회 | ❌ 필요 없음 |
| SELECT INTO CORRESPONDING FIELDS OF TABLE | 다수의 데이터를 Internal Table에 할당 | ❌ 필요 없음 |
| SELECT ... ENDSELECT | 반복적으로 데이터를 처리할 때 사용 | ✅ 필요함 |
✅ 5. 핵심 요약
1️⃣ SELECT SINGLE은 조건에 맞는 한 건의 데이터만 조회하며, ENDSELECT가 필요 없다.
2️⃣ SELECT INTO CORRESPONDING FIELDS OF TABLE은 여러 건의 데이터를 Internal Table에 한 번에 할당하며, ENDSELECT가 필요 없다.
3️⃣ SELECT ... ENDSELECT는 반복적으로 데이터를 처리할 때 사용되며, ENDSELECT가 반드시 필요하다.


'SAP ABAP > 기본' 카테고리의 다른 글
| Transparent Table(트랜스페런트 테이블) (0) | 2025.01.27 |
|---|---|
| Internal Tables (인터널 테이블) 정렬(sort), 삭제 및 요약 정리 (0) | 2025.01.27 |
| Internal Tables (인터널 테이블) 추가, 수정 및 Loop문을 통해 Access하는 방법 (0) | 2025.01.27 |
| Internal Tables (인터널 테이블) 개요 및 변수 선언 (0) | 2025.01.26 |
| Structures Variable (스트럭쳐 타입) (0) | 2025.01.26 |