조회 화면에서 주문번호가 123으로 보여서 프로그램에 WHERE order_no = '123'을 적었는데 한 건도 나오지 않는 일이 있습니다. 엑셀에서 올린 번호로 같은 조회를 해도 마찬가지입니다. 덤프도 구문 오류도 없고 결과만 비어 있습니다. 이 글을 읽고 나면 화면에 보이는 값과 저장된 값이 왜 다른지, 코드에서 언제 직접 변환해야 하는지, 변환이 기대대로 되지 않는 값은 무엇인지 구별할 수 있습니다.
예시는 모두 가상입니다. 도메인 ZDEMO_ORDNO(CHAR 10, 변환 루틴 ALPHA)를 쓰는 데이터 요소 ZDEMO_ORDER_NO, 그 필드 ORDER_NO를 가진 테이블 ZDEMO_ORDERS를 가정합니다. 코드는 실제 시스템에서 실행하지 않았고, 동작의 근거는 ABAP 키워드 문서 7.58판과 7.50판의 Conversion Exits, 문자열 템플릿 서식 옵션, c 타입 대입 규칙입니다. 문서 본문은 영어입니다.
화면의 123과 저장된 0000000123
도메인에 변환 루틴(conversion exit)을 걸면 같은 값이 두 가지 모양을 갖습니다. 사람이 보고 입력하는 표시 형식과, ABAP 데이터 객체와 데이터베이스가 쓰는 내부 형식입니다. 변환 루틴은 CONVERSION_EXIT_ALPHA_INPUT과 CONVERSION_EXIT_ALPHA_OUTPUT 두 함수 모듈로 이루어지며, 이름의 ALPHA가 루틴 이름입니다. INPUT은 표시 형식을 내부 형식으로, OUTPUT은 내부 형식을 표시 형식으로 바꿉니다.
ALPHA의 INPUT은 숫자만으로 된 값을 오른쪽으로 붙이고 앞을 0으로 채웁니다. 그래서 화면에 123을 입력하면 프로그램과 테이블에는 0000000123이 들어갑니다. 출력할 때는 OUTPUT이 앞의 0을 지워 다시 123으로 보여 줍니다. 사람은 늘 123을 보지만 저장된 값은 처음부터 0000000123입니다.
여기서 핵심은 변환이 언제 일어나느냐입니다. 문서가 정한 자리는 두 곳뿐입니다. 하나는 화면(dynpro) 필드와 ABAP 데이터 객체 사이에서 값이 오갈 때로, 입력이 ABAP으로 넘어갈 때 INPUT이, ABAP 값이 화면 필드로 갈 때 OUTPUT이 자동으로 실행됩니다. 다른 하나는 도메인을 참조해 선언한 변수를 WRITE나 WRITE TO로 서식화할 때로, 이때는 OUTPUT이 기본으로 실행됩니다. 대입, 비교, ABAP SQL은 이 목록에 없습니다.
위 예시 화면의 1번처럼 이 도메인의 데이터 타입은 NUMC가 아니라 CHAR입니다. 숫자처럼 보이지만 문자 필드라서 대입만으로는 0이 붙지 않습니다. 2번의 변환 루틴 ALPHA가 화면 입출력에서 0을 붙이고 지우는 역할을 맡고, 3번처럼 이 도메인을 쓰는 테이블 필드에는 0000000123 모양으로 저장됩니다.
코드에 적은 '123'은 변환되지 않는다
프로그램 안에서 lv_order = '123'.이라고 쓰면 c 타입 대입 규칙만 적용됩니다. 문자는 왼쪽부터 채워지고 남은 일곱 자리는 공백입니다. 이 값으로 SELECT ... WHERE order_no = @lv_order를 실행하면 데이터베이스는 공백이 붙은 123과 저장된 0000000123을 비교하므로 맞는 행이 없습니다. 결과 집합이 비면 SELECT는 sy-subrc를 4로 둡니다. 파일 업로드, RFC나 API로 받은 값, 다른 시스템에서 복사한 번호도 화면을 거치지 않았으니 같은 처지입니다.
정상 경로는 비교하기 전에 직접 내부 형식으로 바꾸는 것입니다. 문자열 템플릿의 서식 옵션 ALPHA = IN을 쓰면 lv_order = |{ lv_input ALPHA = IN }|.처럼 쓸 수 있고, 문서는 이 옵션이 CONVERSION_EXIT_ALPHA_INPUT·_OUTPUT과 같은 기능이라고 설명합니다. 반대로 내부 값을 사람에게 보여 줄 문자열로 만들 때는 ALPHA = OUT을 씁니다. 이 옵션은 string, c, n 타입에만 쓸 수 있고, WIDTH와 CASE 말고 다른 서식 옵션과 함께 쓸 수 없습니다.
필드 타입이 n(숫자 텍스트)이라면 이야기가 다릅니다. c에서 n으로 대입하면 숫자 문자만 오른쪽으로 옮겨지고 앞이 0으로 채워지므로 '123'이 대입만으로 0000000123이 됩니다. 대신 숫자가 아닌 문자는 말없이 버려집니다. 같은 "숫자 번호"라도 도메인이 CHAR+ALPHA인지 NUMC인지에 따라 코드에서 할 일이 달라지므로, SE11에서 데이터 타입부터 확인하는 것이 순서입니다.
선택 화면도 같은 원리로 움직입니다. PARAMETERS p_order TYPE zdemo_order_no.처럼 사전 타입을 참조하면 입력 필드가 그 도메인의 화면 속성을 받아 변환 루틴이 실행될 수 있으므로, 사용자가 123을 입력해도 프로그램에는 0000000123이 들어옵니다. TYPE c LENGTH 10으로 선언하면 이 연결이 없으므로 코드에서 직접 바꿔야 합니다. 같은 프로그램을 화면에서 돌리면 되고 배치나 테스트 코드에서는 안 되는 경우, 값이 어느 길로 들어왔는지부터 보면 됩니다.
ALPHA가 0을 붙이지 않는 값
ALPHA = IN은 앞뒤 공백을 빼고 끊김 없는 숫자열일 때만 0을 채웁니다. A-123처럼 문자가 섞였거나 12 34처럼 숫자 사이에 공백이 있으면 아무것도 붙이지 않고 왼쪽 정렬한 그대로 둡니다. 같은 도메인에 숫자 번호와 영문이 섞인 번호가 함께 있다면 저장된 모양도 둘로 나뉩니다. 숫자 번호는 0이 붙고, 영문이 섞인 번호는 입력한 그대로입니다.
결과 길이도 확인해야 합니다. 서식 옵션 WIDTH 없이 변수 하나만 담은 템플릿을 c, n, d, t 같은 고정 길이 필드에 대입하면 대상 필드의 길이가 기준이고, 표현식이나 함수 호출이면 원래 필드의 길이가 기준입니다. 7.58판 문서의 예에서는 c 10 값 0000012345를 c 5 필드에 넣을 때, 변수를 그대로 쓰면 12345가 되고 테이블 식을 쓰면 길이 10으로 0000012345를 만든 뒤 대입에서 잘려 00000이 됩니다. 길이가 다른 필드끼리 변환할 때는 템플릿에 변수 하나만 두거나 WIDTH를 지정하는 편이 안전합니다.
반대 방향의 함정도 있습니다. 어떤 프로그램이 변환 없이 '123'을 그대로 넣어 저장했다면 그 행은 0 없이 저장되어 있을 수 있고, 이번에는 화면에서 123을 입력해 0000000123으로 찾을 때 그 행이 나오지 않습니다. 이것은 대입 규칙에서 따라 나오는 결과로, 실제 시스템에서 재현한 사례가 아닙니다. 조회가 안 될 때는 코드의 값과 함께 저장된 값의 실제 모양을 확인하세요.
릴리스와 확인 범위
문자열 템플릿의 ALPHA 옵션과 그 규칙(숫자열 판정, 앞 0 채우기와 지우기, 결과 길이 결정)은 7.50판과 7.58판 문서에 같은 내용으로 있습니다. 7.58판에는 위의 c 5 대입 예제가 본문에 들어 있고 7.50판은 별도 실행 예제로 안내합니다. 7.50보다 오래된 릴리스는 확인하지 않았으므로, 그런 시스템에서는 자기 릴리스의 문서에서 이 옵션이 있는지 확인하고, 없다면 같은 기능의 함수 모듈을 호출하세요. 변환 루틴은 화면 입출력과 WRITE 때만 자동으로 실행된다는 범위도 두 판이 같습니다. WRITE ... USING NO EDIT MASK를 쓰면 이 자동 OUTPUT 변환을 끌 수 있습니다.
조회가 비었을 때 볼 것
값이 분명히 있는데 SELECT가 비어 있으면 세 가지를 봅니다. 그 필드의 도메인에 변환 루틴이 있는가. 비교하는 값이 화면을 거쳐 들어왔는가, 코드나 파일에서 왔는가. 데이터 타입이 CHAR인가 NUMC인가. 하나만 기억한다면 이것입니다. 화면에 보이는 값은 표시 형식이고, 코드와 데이터베이스는 내부 형식으로 비교합니다. 그 사이를 이어 주는 변환은 화면과 WRITE 밖에서는 직접 불러야 일어납니다.
이 기록에 대화를 더해 주세요.
궁금한 점, 다른 접근, 직접 해 본 결과를 나눠 주세요.
로그인 상태 확인 중…
댓글을 불러오는 중…