SAP BOX

'26/10/07 UPDATE

ABAP / FIELD NOTES

AT NEW로 고객별 소계를 냈는데 왜 줄마다 끊기고 이름이 ****로 나올까

AT NEW kunnr는 kunnr와 그 왼쪽 열 전부를 그룹 키로 보고, INTO로 읽으면 AT 블록 안에서 키 오른쪽 열이 별표와 초기값으로 바뀝니다. 가상 매출 네 행으로 원인과 열 순서·값 미리 담기·GROUP BY 세 가지 해법, WHERE 조건과 릴리스별 설명 차이를 봅니다.

매출 내부 테이블을 고객별로 묶어 소계를 내려고 LOOP 안에 AT NEW kunnr와 AT END OF kunnr를 넣었는데, 고객이 두 명뿐인데도 소계가 행 수만큼 찍히고, 머리글에 넣은 고객 이름은 ********로 나오는 일이 있습니다. 덤프도 구문 오류도 없습니다. 이 글을 읽고 나면 AT NEW가 무엇을 그룹 키로 보는지, AT 블록 안에서 작업 영역이 왜 바뀌는지 코드에서 짚어 내고, 고칠 방법 세 가지 가운데 하나를 고를 수 있습니다.

예시는 가상 매출 네 행입니다. 고객 C-100(ALPHA TRADING)에 전표 9000000001(100.00)과 9000000002(250.00), 고객 C-200(BETA SUPPLY)에 9000000003(80.00)과 9000000004(120.00)가 있습니다. 고객, 전표번호, 금액, 프로그램 이름은 모두 지어낸 것이고, 코드는 실제 시스템에서 실행하지 않았습니다. 동작의 근거는 ABAP 키워드 문서의 AT(그룹 레벨 처리) 설명이며, 7.58판과 7.50판에서 아래 핵심 규칙은 같습니다.

AT NEW kunnr는 kunnr 왼쪽 열까지 본다

첫 번째 증상의 원인은 행 구조의 열 순서입니다. 행 구조가 belnr(전표번호), kunnr(고객), name, amount 순서라고 해 봅시다. AT NEW kunnr는 kunnr 한 열이 바뀔 때가 아니라, kunnr와 그 왼쪽에 있는 모든 열 가운데 하나라도 바뀔 때 그룹이 바뀐 것으로 봅니다. 문서의 표현으로는 지정한 열과 그 왼쪽 열들의 내용이 그룹 키입니다.

그러면 이 예에서 그룹 키는 belnr+kunnr입니다. 전표번호는 행마다 다르므로 키도 행마다 바뀌고, AT NEW kunnr는 네 번, AT END OF kunnr도 네 번 실행됩니다. 그 안에서 SUM을 부르면 그룹이 한 행짜리라 소계는 각 행 금액과 똑같습니다. 고객별 합계를 낸 것처럼 보이지만 실은 행을 하나씩 다시 찍은 셈입니다.

SAP 노트

AT NEW kunnr의 그룹 키는 kunnr 하나가 아니다

가상 매출 4행: 고객 C-100 두 건, C-200 두 건 (전표번호 순)

  1. 행 구조 belnr · kunnr · name · amount

    AT NEW × 4

    • 그룹 키 = 왼쪽의 belnr + kunnr
    • 전표번호가 행마다 다르니 키도 행마다 바뀜
    • AT NEW kunnr 4번, 소계도 4줄
    • 소계 = 각 행 금액 그대로
  2. kunnr를 맨 앞에 두고 SORT BY kunnr belnr

    AT NEW × 2

    • 그룹 키 = kunnr
    • C-100 → C-200에서만 키가 바뀜
    • AT NEW kunnr 2번
    • 소계 C-100 350.00 · C-200 200.00

고객·전표번호·금액은 가상입니다. 규칙은 ABAP 키워드 문서 7.58판·7.50판의 AT(그룹 레벨 처리) 설명이며, 코드는 실행하지 않았습니다.

AT NEW와 AT END OF는 지정한 열과 그 왼쪽 열 전부를 그룹 키로 봅니다. 열의 위치가 정렬만큼 중요합니다.

고치는 첫 번째 방법은 그룹 키로 쓸 열을 행 구조의 맨 앞에 두고, 그 순서대로 정렬하는 것입니다. 행 구조를 kunnr, belnr, name, amount로 바꾸고 SORT lt_sales BY kunnr belnr를 하면 그룹 키는 kunnr뿐이고, C-100에서 C-200으로 넘어갈 때만 그룹이 바뀝니다. 소계는 C-100 350.00, C-200 200.00 두 줄입니다.

정렬도 빠뜨리면 안 됩니다. 그룹은 읽는 순서대로 이웃한 행 가운데 그룹 키가 같은 행의 묶음입니다. 테이블이 C-100, C-200, C-100 순서라면 C-100이 두 그룹으로 나뉘어 소계도 두 번 나옵니다. AT는 같은 키의 행을 찾아 모으지 않고, 바로 앞뒤 행과만 비교합니다.

AT 블록 안에서 이름이 별표가 되는 이유

두 번째 증상은 LOOP AT lt_sales INTO ls_sale처럼 작업 영역으로 읽을 때 생깁니다. AT와 ENDAT 사이에 들어가는 순간 작업 영역 ls_sale이 잠시 바뀝니다. 현재 그룹 키의 열은 그대로 두고, 키 오른쪽에 있는 문자형 평면 열(c, n, d, t 타입처럼 길이가 고정된 문자형)은 모든 자리가 *로, 나머지 열(숫자형 등)은 초기값으로 채워집니다. ENDAT을 지나면 현재 행 내용으로 다시 채워집니다.

SAP 노트

AT 블록 안에서 작업 영역은 잠시 바뀐다

LOOP AT lt_sales INTO ls_sale, 행 구조 kunnr · belnr · name · amount, 첫 행을 읽을 때

  1. AT 앞 (현재 행)

    • kunnr C-100
    • belnr 9000000001
    • name ALPHA TRADING
    • amount 100.00
  2. AT NEW kunnr 안

    • kunnr C-100 (키는 그대로)
    • belnr **********
    • name 전부 *
    • amount 0.00 (초기값)
  3. ENDAT 뒤

    • 현재 행 내용으로 다시 채워짐
    • name ALPHA TRADING
    • amount 100.00

데이터는 가상입니다. 키 오른쪽의 문자형 평면 열(c, n, d, t)은 모든 자리가 *, 나머지는 초기값이 됩니다. ASSIGNING·REFERENCE INTO로 읽으면 행이 바뀌지 않습니다.

INTO로 읽을 때 AT NEW 안에서 고객 이름을 쓰면 별표가 나옵니다. 이름은 키 안에 넣거나 AT 앞에서 따로 담아 둡니다.

그래서 AT NEW kunnr 안에서 고객 머리글로 ls_sale-name을 쓰면 별표가 나오고, ls_sale-amount는 0입니다. AT FIRST와 AT LAST에는 그룹 키 열이 없으므로 문자형 열 전부가 *, 나머지는 초기값입니다.

이름을 쓰려면 방법이 둘 있습니다. 이름이 고객마다 하나뿐이라면 name을 kunnr 바로 뒤에 두고 AT NEW name으로 바꿔 이름까지 그룹 키에 넣을 수 있습니다. 아니면 아래 화면의 2번처럼 AT 앞에서 lv_name = ls_sale-name으로 담아 둡니다. AT 앞의 문장은 매 행마다 실행되므로, AT END OF 안에서는 그룹 마지막 행의 이름이 들어 있습니다.

SAP GUI ABAP 편집기 화면. kunnr를 맨 앞에 둔 행 구조 ty_sale 선언, SORT BY kunnr belnr 뒤 LOOP AT INTO에서 AT 앞에 이름을 lv_name에 담고 AT END OF kunnr 안에서 SUM으로 소계를 출력하는 코드, 7.40 SP08 이후 GROUP BY ls_sale-kunnr와 LOOP AT GROUP으로 그룹 합계를 더해 출력하는 코드에 번호 네 개가 표시되어 있다.
고객별 소계를 AT END OF와 GROUP BY로 쓴 예시 화면. ZDEMO_AT_NEW는 가상 프로그램이며 코드는 실행하지 않았다.

ASSIGNING이나 REFERENCE INTO로 읽으면 테이블 행 자체는 AT 블록에 들어갈 때 바뀌지 않아 별표 문제가 없습니다. 다만 SUM은 INTO 작업 영역이 있어야 쓸 수 있고, ASSIGNING 루프에서 부르면 런타임 오류 SUM_NO_ASSIGNING이 납니다. SUM은 위 화면의 3번처럼 현재 그룹 행들의 키 오른쪽 숫자 열 합계를 작업 영역에 넣습니다. 또 INTO 작업 영역을 루프 안에서 직접 고치거나 루프 중에 테이블을 바꾸면 그룹 처리가 기대대로 되지 않습니다. 문서가 금지하는 규칙입니다.

LOOP 조건과 릴리스에 따른 차이

LOOP … WHERE로 일부 행만 읽을 때는 문서의 판에 따라 설명의 깊이가 다릅니다. 7.50판은 조건이 연속한 행 묶음을 골라야 한다는 규칙만 둡니다. 7.58판은 더 구체적입니다. 그룹은 조건과 상관없이 테이블의 모든 행으로 정해지고, 그룹이 바뀌는 행을 조건 때문에 읽지 않으면 그 AT 블록은 실행되지 않으며, 이런 코드에는 확장 프로그램 검사 메시지가 나올 수 있다고 적습니다.

정렬된 예에서 WHERE amount > 100을 붙이면 C-100의 첫 행(100.00)과 C-200의 첫 행(80.00)을 읽지 않으므로 두 고객 모두 AT NEW kunnr가 실행되지 않습니다. 금액 조건처럼 그룹 중간을 건너뛰는 조건은 AT와 함께 쓰지 말고, 먼저 필요한 행만 다른 테이블로 옮긴 뒤 그룹 처리를 하는 편이 안전합니다. 쓰는 시스템의 릴리스에 맞는 판의 설명을 확인하세요.

SAP 노트

구조를 고쳤는데도 그룹이 어긋나는 경우

정렬, LOOP 조건, 그리고 7.40 SP08부터 쓸 수 있는 GROUP BY

  • 정렬하지 않음

    • C-100, C-200, C-100 순서
    • 그룹은 연속한 행끼리만 묶임
    • C-100 소계가 두 번 나옴
  • WHERE가 그룹 첫 행을 뺌

    • LOOP … WHERE amount > 100
    • 그룹 변경이 생긴 행을 안 읽으면
    • 그 AT 블록은 실행되지 않음
    • 7.58판에 명시, 7.50판은 연속 블록 규칙만
  • GROUP BY (7.40 SP08부터)

    • LOOP AT … GROUP BY ls-kunnr
    • 같은 키의 행을 모두 한 그룹으로
    • 열 위치·정렬 순서와 무관
    • AT 블록은 쓸 수 없음

값은 가상입니다. AT 문은 GROUP BY 그룹 루프와 LOOP AT GROUP 안에서 쓸 수 없으므로, 소계는 LOOP AT GROUP으로 행을 돌며 직접 더합니다.

AT NEW는 읽는 순서대로 이웃한 행만 비교합니다. 정렬과 LOOP 조건이 그룹을 바꾸지 않는지 확인하고, 새 코드라면 GROUP BY를 검토합니다.

세 번째 방법은 7.40 SP08부터 쓸 수 있는 LOOP AT … GROUP BY입니다. 같은 그룹 키를 가진 행을 모두 한 그룹으로 모으므로 열의 위치나 정렬 순서에 기대지 않습니다. 화면의 4번처럼 INTO ls_sale로 그룹을 돌면 ls_sale에는 그룹의 첫 행이 들어 있어 이름도 별표 없이 쓸 수 있고, 금액은 LOOP AT GROUP으로 행을 돌며 더합니다. 문서도 가능하면 GROUP BY를 권합니다. 대신 GROUP BY 루프와 LOOP AT GROUP 안에서는 AT를 쓸 수 없습니다. 그룹 순서는 기본적으로 그 키가 처음 나온 순서이고, ASCENDING이나 DESCENDING을 붙이면 키 순서로 정렬됩니다.

코드에서 확인할 것

기존 프로그램의 AT NEW와 AT END OF마다 세 가지를 봅니다. 지정한 열 왼쪽에 그룹과 상관없는 열이 있지 않은가? 바로 앞에 그 열들의 순서대로 정렬하고 있는가? AT 블록 안에서 키 오른쪽 열을 읽고 있지 않은가? 하나라도 걸리면 열 순서를 고치거나, 값을 미리 담거나, GROUP BY로 옮깁니다.

하나만 기억한다면 이것입니다. AT NEW f는 "f가 바뀔 때"가 아니라 "행 구조에서 f까지의 앞부분이 바뀔 때"이고, 그 블록 안의 작업 영역은 현재 행이 아닙니다.

끝 · END OF NOTE목록으로
COMMENTS BOX

이 기록에 대화를 더해 주세요.

궁금한 점, 다른 접근, 직접 해 본 결과를 나눠 주세요.

최신순

로그인 상태 확인 중…

댓글을 불러오는 중…