-
SAP HANA SQLScript - 8장 명령형 로직 (8.1~8.3)SAP 2026. 5. 30. 20:54sqlscript_ch8_1to8_3.html0.03MB
SAP HANA SQLScript - 8장 명령형 로직 (8.1~8.3) 📘 SAP HANA SQLScript Reference
Chapter 8 — Imperative SQLScript Logic (8.1 ~ 8.3)SAP HANA SQLScript Reference for SAP HANA Platform | pp. 112~140 정리
📋 목차
1. 8장 개요 — Imperative SQLScript Logic
이 장은 반복문(loop)과 조건문(conditional) 같은 명령형 언어 구성요소를 다룬다. 명령형 로직은 데이터 흐름을 여러 개로 분할하므로, 선언형 로직에 비해 성능이 떨어질 수 있다. 필요한 경우에만 선택적으로 사용하는 것이 권장된다.💡 관련 섹션 Declarative SQLScript Logic → p.88 참조2. 8.1 Scalar Variables (스칼라 변수)
문법 (Syntax)
DECLARE <sql_identifier> [{,<sql_identifier>}...] [CONSTANT] <type> | AUTO [NOT NULL] <proc_default> <proc_default> ::= (DEFAULT | '=') <value> | <expression> <value> !!= An element of the type specified by <type>핵심 설명
- 로컬 변수는
DECLARE키워드로 선언하며, 초기값을 함께 지정할 수 있다. - 기본값은 NULL로 초기화된다.
- 변수 참조 시에는
:var형식, 대입 시에는var형식을 사용한다. - 대입 연산자는
=을 권장한다 (:=도 지원되지만 SAP 권장사항이 아님). - 변수명은 영숫자,
#,$,_를 지원하며, 대소문자 구분 이름도 가능하다.
💡 Tip 변수 값 읽기는:var, 변수에 값 대입은var를 사용한다.ℹ️ Note — 대소문자 처리 더블쿼트 없는 SQL 식별자는 서버에서 대문자로 변환된다. 예:DECLARE myvar INT→ 내부적으로MYVAR로 처리. 대소문자를 유지하려면 더블쿼트 필수:DECLARE "MyVar" INT예제
CREATE PROCEDURE proc (OUT z INT) LANGUAGE SQLSCRIPT READS SQL DATA AS BEGIN DECLARE a int; DECLARE b int = 0; DECLARE c int DEFAULT 0; t = select * from baseTable; select count(*) into a from :t; b = :a + 1; z = :b + :c; end;-- 스칼라 UDF 결과를 변수에 대입 (1 출력) DECLARE i INTEGER DEFAULT 0; SELECT SUDF_ADD(:input1, :input2) into i from dummy; -- 스칼라 UDF 다중 출력 변수 대입 DECLARE i INTEGER DEFAULT 0; DECLARE j NVARCHAR(5); (i,j) = SUDF_EXPR(:input1); -- 대소문자 구분 변수 참조 DO BEGIN DECLARE myvar INT = 0; DECLARE "MyVar" INT = 1; SELECT :myvar, /* MYVAR - 첫 번째 변수 */ :"MyVar" /* MyVar - 두 번째 변수 */ from dummy; END;2-1. 8.1.1 SELECT INTO with DEFAULT Values
SELECT INTO는 결과셋을 스칼라 변수에 할당하는 데 널리 사용된다. 결과가 빈 셋(empty result set)인 경우 기존에는 exit handler가 필요했지만, DEFAULT 절을 사용하면 exit handler 없이 기본값을 적용할 수 있다.문법
SELECT <select_list> INTO <var_name_list> [DEFAULT <scalar_expr_list>] <from_clause> [<where_clause>] [<group_by_clause>] [<having_clause>] [<order_by_clause>] [<limit>]; [EXEC | EXECUTE IMMEDIATE] <string_expression> [ INTO <var_name_list> [DEFAULT <scalar_expr_list>] ] [ USING <scalar_expr_list> ] -- 배열 인덱스를 이용한 INTO도 지원 <var_name> ::= <identifier> | <identifier> '[' <index> ']'예제 — 배열 인덱스 INTO
DROP TABLE T1; CREATE TABLE T1 (A INT NOT NULL, B VARCHAR(10)); DO BEGIN DECLARE A_COPY INT ARRAY; DECLARE B_COPY VARCHAR(10) ARRAY; -- 빈 결과 시 DEFAULT 적용: A_COPY[1]=-2+1=-1, B_COPY[1]=NULL SELECT A, B INTO A_COPY[1], B_COPY[1] DEFAULT -2+1, NULL FROM T1; SELECT :A_COPY[1], :B_COPY[1] from dummy; -- (-1, ?) -- EXEC INTO에 DEFAULT 적용 EXEC 'SELECT A FROM T1' INTO A_COPY[1] DEFAULT 2; SELECT :A_COPY[1], :B_COPY[1] from dummy; -- (2, ?) INSERT INTO T1 VALUES (0, 'sample0'); SELECT A, B INTO A_COPY[1], B_COPY[1] DEFAULT 5, NULL FROM T1; SELECT :A_COPY[1], :B_COPY[1] from dummy; -- (0, 'sample0') 실제값 사용 END;2-2. 8.1.2 SQL in Scalar Expressions
SQLScript에서 SELECT를 스칼라 표현식 내의 서브쿼리로 사용할 수 있다. 단, 결과셋이 정확히 1행 × 1열이어야 한다.
- 스칼라 값 대입의 서브쿼리로 사용 가능
- 조건식의 서브쿼리로 사용 가능
-- 스칼라 대입 x = (SELECT TOP 1 val from mytab) * 10; -- 조건식 내 사용 IF (SELECT MAX(val) FROM mytab) > 100 THEN ... -- 결과가 0건이면 null 반환 create table empty_tab(i int); do begin declare n int = (select * from empty_tab) + 1; -- n = null end;⚠️ 주의사항 결과가 2열 이상이면 ERR-00269 (too many values), 2행 이상이면 ERR-01300 (too many rows) 오류 발생.
우변 전체가SELECT문으로만 구성된 경우 (x = SELECT * FROM tab) 테이블 변수 대입으로 처리됨 — 스칼라로 쓰려면SELECT INTO를 사용할 것.⚠️ 제한 (Limitation)AUTO타입에는 서브쿼리를 사용할 수 없다.
declare n auto = (select 10 from dummy) + 1; -- ERR-000073. 8.2 Table Variables (테이블 변수)
테이블 변수는 표 형식 데이터 구조를 참조하는 변수이다. 테이블 파라미터도 동일한 규칙이 적용된다. 관련 내용: Table Variable Type Definition → p.933-1. 8.2.1 Table Variable Operators
8.2.1.1 Index-Based Cell Access (인덱스 기반 셀 접근)
테이블 변수의 특정 셀에 직접 읽기/쓰기 접근이 가능하다.
<table_variable>.<column_name>[<index>]구분 구문 설명 쓰기 intab.A[2] = 5;2번 행의 A 컬럼에 값 5 쓰기 읽기 outvar = :intab.B[100];100번 행의 B 컬럼 값 읽기 (읽기 시 콜론 :필요)ℹ️ 제한사항- 물리 테이블에는 접근 불가
SELECT :MY_TABLE_VAR.COL[55] AS A FROM DUMMY형태는 지원 안 됨 — 먼저 스칼라 변수에 할당할 것- 인덱스 범위: 1 ~ 2^31-2 (2,147,483,646)
create procedure procTCA ( IN intab TABLE(A INTEGER, B VARCHAR(20)), OUT outtab TABLE(A INTEGER, B VARCHAR(20)) ) AS BEGIN intab.A[2] = 5; -- 2행의 A 컬럼 수정 outtab = select * from :intab; END; -- 읽기 예시 create procedure procTCA ( IN intab TABLE(A INTEGER, B VARCHAR(20)), OUT outvar VARCHAR(20) ) AS BEGIN outvar = :intab.B[100]; -- 100행의 B 컬럼 읽기 END;8.2.1.2 Modifying the Content of Table Variables
SQL 레이어를 거치지 않고 테이블 변수의 내용을 직접 수정할 수 있어 성능이 향상된다. 단, 데이터 구체화(materialization)가 필요하므로 선언형 로직과 달리 메모리를 사용한다.
ℹ️ Note 모든 위치 인덱스의 유효 범위: 1 ~ 2^31-1▸ Inserting Data Records
-- 전체 컬럼 삽입 (index 지정 시 해당 위치에 삽입, 생략 시 맨 끝에 추가) :<table_variable>.INSERT((<value1>, ..., <valueN>) [, <index>]) -- 일부 컬럼만 삽입 (생략 컬럼은 NULL) :<table_variable>.(<col1>, ..., <colN>).INSERT((<val1>, ..., <valN>) [, <index>]) -- 다른 테이블 변수 삽입 :<target>[.(<col_list>)].INSERT(:<source_table_var> [, <position>])-- 기본 사용 예시 :OT.INSERT(('Section ' || K, VSUM), IDX); -- 일부 컬럼만 :tab_a.(col1, COL2).insert(:tab_b); -- 다른 테이블 변수 삽입 - 컬럼 순서 매핑 주의 -- SOURCE_TAB(X,A,B,C), TARGET_TAB(A,B,C,D) -- :target_tab.insert(:source_tab) → X→A, A→B, B→C, C→D -- :TARGET_TAB.(D, A, B, C).insert(:SOURCE_TAB) → X→D, A→A, B→B, C→C▸ Updating Data Records
-- 전체 컬럼 업데이트 (index 필수) :<table_variable>.UPDATE((<val1>, ..., <valN>), <index>) <table_variable>[<index>] = (<val1>, ..., <valN>) -- 일부 컬럼만 (생략 컬럼은 변경 없음) :<table_variable>.(<col1>, ..., <colN>).UPDATE((<val1>, ..., <valN>), <index>) <table_variable>.(<col1>, ..., <colN>)[<index>] = (<val1>, ..., <valN>)ℹ️ Note 원래 테이블 크기를 벗어난 위치에도 값 설정 가능. INSERT처럼 중간 레코드는 NULL로 채워진다.▸ Deleting Data Records
구문 동작 :<table_variable>.DELETE([ <index> ])index 지정 시 해당 행 삭제, 생략 시 전체 삭제 :<table_variable>.DELETE(<start>..<end>)범위 삭제 (start~end 행) :<table_variable>.DELETE(<array_of_integers>)인덱스 배열로 선택 삭제 ℹ️ Note- index가 테이블 크기보다 크면 아무 동작도 하지 않음
- end index < start index이면 오류 발생
- 배열 삭제 시 배열에 잘못된 인덱스(예: 0)가 있으면 오류 발생
-- 계층 구조 탐색 예 (DELETE 활용) CREATE PROCEDURE CALC_LEVEL (IN IT HIER, IN ROOT VARCHAR(30), OUT OT_LEVEL TABLE(NODE VARCHAR(30), L INT)) AS BEGIN DECLARE STACK TABLE(NODE VARCHAR(30), L INT); STACK[1] = (ROOT, 1); WHILE NOT IS_EMPTY(:STACK) DO DECLARE CURR_NODE VARCHAR(30) = :STACK.NODE[1]; DECLARE CURR_LEVEL INT = :STACK.L[1]; CHILDREN = SELECT CHILD FROM :IT WHERE PARENT = CURR_NODE; :OT_LEVEL.INSERT((CURR_NODE, CURR_LEVEL)); :STACK.DELETE(1); -- 스택 팝 FOR I IN 1..RECORD_COUNT(:CHILDREN) DO :STACK.INSERT((:CHILDREN.CHILD[I], CURR_LEVEL + 1)); END FOR; END WHILE; END;8.2.1.3 UNNEST Function
하나 이상의 배열 및/또는 테이블 변수를 결합해 테이블로 변환한다. 결과는 반드시 테이블 변수에 대입해야 한다.
<variable_name> = UNNEST(<unnest_param> [{, <unnest_param>}]) [WITH ORDINALITY] [AS (<column_specifier> [{, <column_specifier>}]) ] <unnest_param> ::= :table_variable | :array_variable | :array_function <column_specifier> ::= '*' | '(' <projection_aliasing_list> ')' | <column_name>-- 기본 사용 CREATE PROCEDURE ARRAY_UNNEST_SIMPLE(OUT rst TABLE(":ARR_ID" INT, ":ARR_NAME" NVARCHAR(10))) READS SQL DATA AS BEGIN DECLARE arr_id INTEGER ARRAY = ARRAY(1, 2); DECLARE arr_name NVARCHAR(10) ARRAY = ARRAY('name1', 'name2', 'name3'); rst = UNNEST(:arr_id, :arr_name); -- 결과: {1,name1}, {2,name2}, {?,name3} ← 짧은 쪽은 NULL END; -- AS 절로 컬럼명 변경 rst = UNNEST(:arr_id, :arr_name) AS (ID, NAME); -- WITH ORDINALITY (순서 컬럼 추가) CREATE PROCEDURE ARRAY_UNNEST(OUT rst TABLE(AMOUNT INTEGER, SEQ INTEGER)) LANGUAGE SQLSCRIPT READS SQL DATA AS BEGIN DECLARE amount INTEGER ARRAY = ARRAY(10, 20); rst = UNNEST(:amount) WITH ORDINALITY AS ("AMOUNT", "SEQ"); -- 결과: {10,1}, {20,2} END; -- 테이블 변수 UNNEST (projection aliasing) t0 = select * from tab0 order by a asc; t1 = select * from tab0 order by a desc; lt = unnest(:t0, :t1) as (*, (a as b)); -- t0의 모든 컬럼(*) + t1의 a 컬럼을 b로 리네임ℹ️ Default Column Names 컬럼 지정자 없으면 자동 생성: COL1, COL2, ... / 중복 시 COL3→COL4 순으로 번호 증가. 순서 컬럼은 기본적으로 "ORDINALITY", 이미 존재하면 "ORDINALITY1", "ORDINALITY2" ...Result LHS Type RHS Type Potential run-time error NOT NULL NOT NULL Compile-time error NOT NULL Nullable No error Nullable NOT NULL No error Nullable Nullable ℹ️ Note Array 타입은 항상 nullable이다.8.2.1.4 IS_EMPTY — 빈 테이블 확인
IS_EMPTY( <table_name> | <table_variable> )테이블 또는 테이블 변수가 비어 있으면
true, 아니면false를 반환한다. IF문, WHILE 루프, 스칼라 대입에서 사용 가능.⚠️ 주의 IS_EMPTY는 SQL 쿼리나 표현식 내에서는 직접 사용할 수 없다.CREATE PROCEDURE PROC_IS_EMPTY (IN tabvar TABLE(ID INTEGER), OUT outtab TABLE(ID INTEGER)) AS BEGIN IF IS_EMPTY(:tabvar) THEN RETURN; END IF; CALL INTERNAL_LOGIC (:tabvar, outtab); END;8.2.1.5 RECORD_COUNT — 레코드 수 조회
RECORD_COUNT( <table_name> | <table_variable> )테이블 또는 테이블 변수의 레코드 수를 BIGINT로 반환한다. IF문, 루프, 스칼라 대입 등 표현식이 허용되는 모든 곳에서 사용 가능.
⚠️ 주의 RECORD_COUNT는 SQL 쿼리(SELECT 등)에서는 사용할 수 없다.DO (IN inTab TABLE(col_a int) => TAB, OUT v INT => ?) BEGIN DECLARE i int; v = 0; FOR i IN 1 .. RECORD_COUNT(:inTab) DO v = :v + :inTab.col_a[:i]; END FOR; END8.2.1.6 Search in Table Variables — 키 검색
position = <tabvar>.SEARCH((<column_list>), (<value_list>) [, <start_position>])테이블 변수에서 키-값 쌍으로 효율적인 검색을 수행한다. 컬럼 목록과 값 목록의 크기가 같아야 한다.
start_position기본값은 1 (전체 스캔). 일치하는 첫 번째 레코드 위치를 반환하고, 없으면 NULL을 반환한다.ℹ️ Note SEARCH 함수는 다른 표현식과 함께 사용할 수 있지만, SQL 문 안에서는 직접 사용 불가.-- SEARCH + DELETE + 인덱스 접근 조합 예 DECLARE LT1 TABLE ("Key1"..., "Key2"..., "Val1"...); -- LT1 = ... (초기 상태 참조) pos = :LT1.SEARCH(("Key1", "Key2"), ('I', 3)); -- pos = NULL (없음) :LT1.INSERT(('I', 3, 'X'), 0); -- 삽입 pos = :LT1.SEARCH(("Key1", "Key2"), ('M', 3)); -- pos = 5 :LT1.DELETE(pos); val = :LT1."Val1"[:LT1.SEARCH(("Key1", "Key2"), ('E', 5))]; -- val = 'V12'3-2. 8.2.2 SQL DML Statements on Table Variables
SQLScript 테이블 변수에 SQL DML 문(
INSERT,UPDATE,DELETE)을 직접 사용할 수 있다. 영구 테이블과 문법이 동일하지만, 테이블 변수는 앞에 콜론(:)을 붙여야 한다.DECLARE lt TABLE (a INT, b VARCHAR(20)); INSERT INTO :lt VALUES (1, 'abc'); UPDATE :lt SET b = 'def' WHERE a = 1; DELETE FROM :lt WHERE a = 1;지원되는 제약 조건
- Primary Key 체크
- NOT NULL 체크
CREATE TYPE tt AS TABLE (a INT PRIMARY KEY, b INT NOT NULL); DECLARE lt1 tt; -- 타입 정의의 제약 적용 DECLARE lt2 TABLE (a INT, b INT, c INT NOT NULL, PRIMARY KEY(a, b));다른 구문과의 호환성 (Compatibility)
DML 문으로 조작된 테이블 변수는 SQL 문에서만 사용 가능하다. 아래 표를 참고한다.
구문 DML 조작 후 사용 가능 여부 SELECT * FROM :lt2✅ 가능 INSERT INTO :lt2 (SELECT * FROM :lt1)✅ 가능 CALL nested_proc(:lt2)(파라미터가 IN인 경우)✅ 가능 :lt1.INSERT(:lt2)(INSERT 연산자)❌ 불가 lt2 = SELECT * FROM :lt1(대입 타겟)❌ 불가 💡 DML과 비-DML 변수 간 변환 (Conversion) DML 구문과 비-DML 구문을 함께 써야 하면, 두 개의 테이블 변수를 사용해 서로 변환한다.DECLARE tab_without_dml TABLE (a INT); DECLARE tab_with_dml TABLE LIKE :tab_without_dml; tab_without_dml = SELECT * FROM mytab; -- 비-DML 변수에 할당 -- 비-DML → DML 변환 (데이터 복사) INSERT INTO :tab_with_dml (SELECT * FROM :tab_without_dml); -- DML 작업 수행 DELETE FROM :tab_with_dml WHERE a > 100; -- DML → 비-DML 변환 (데이터 복사) tab_without_dml = SELECT * FROM :tab_with_dml;사용 권장 시나리오
상황 권장 방법 복잡한 WHERE 조건의 UPDATE/DELETE DML 문 사용 복잡한 UPDATE 구문 DML 문 사용 제약 조건 체크 필요 DML 문 사용 일반적인 데이터 조작 SQLScript 테이블 변수 연산자 권장 (더 나은 성능) ⚠️ 제한 (Limitations)- 자율 트랜잭션(autonomous transaction)에서는 사용 불가
- 병렬 실행 블록(parallel execution block)에서는 사용 불가
- 프로시저/함수의 INPUT/OUTPUT 파라미터는 DML 문으로 조작 불가
3-3. 8.2.3 Sorted Table Variables (정렬 테이블 변수)
정렬 테이블 변수는 데이터 레코드를 검색 키(search key)에 의해 항상 정렬 상태로 유지하는 특수한 테이블 변수이다. 대량 데이터에 대한 명령형 알고리즘에서 효율적인 접근을 제공하며, SEARCH 연산자 사용 시 이진 탐색(binary search)이 적용된다.
선언 문법
-- 타입 정의에서 검색 키 지정 CREATE TYPE <name> AS TABLE (<column list>) SQLSCRIPT SEARCH KEY(<key list>) -- 변수 선언에서 검색 키 지정 DECLARE <name> TABLE(<column list>) SEARCH KEY(<key list>) DECLARE <name> <table type> SEARCH KEY(<key list>) -- 프로시저/함수 파라미터 CREATE PROCEDURE <proc> (IN <param> TABLE(<column list>) SEARCH KEY(<key list>))검색 키(Search Key) 동작 방식
Search statement 동작 :LT.SEARCH(B, 1)B 컬럼으로 탐색. 이진 탐색 적용 → 1번 레코드 반환 :LT.SEARCH((B, A), (1, 2))B, A 컬럼으로 탐색. 이진 탐색 적용 → 2번 레코드 반환 :LT.SEARCH((B, C), (1, 15))B=1로 이진 탐색 후 C=15 순차 스캔 → 2번 레코드 반환 :LT.SEARCH(A, 1)첫 번째 키 컬럼 B 없음 → 이진 탐색 불가, 순차 탐색 → 3번 레코드 Output of Search Operator (전체 키 지정 시 특별 동작)
검색 구문 결과 :LT.SEARCH(B, 3)전체 키 미지정 → 불일치 시 NULL 반환 :LT.SEARCH((B, A, C), (1, 2, 20))전체 키 지정 → 불일치 시 음수 반환 (-3: B=1,A=2,C=20인 레코드가 삽입될 위치) 💡 음수 반환값 활용 검색 후 음수 반환 시 해당 위치의 절댓값(-값)에 삽입하면 정렬 순서가 유지된다. 별도 위치 탐색 없이 직접 삽입 가능.동일 키 값을 가진 레코드 순회
DECLARE pos int; DECLARE mytab TABLE (key1 int, key2 int, key3 int, value int) SEARCH KEY(key1, key2, key3); DECLARE keyval1, keyval2 int; ... -- 처음 두 키 컬럼이 특정 값인 레코드 순회 pos = :mytab.SEARCH((key1, key2), (keyval1, keyval2)); IF pos > 0 THEN WHILE :mytab.key1[pos] = keyval1 AND :mytab.key2[pos] = keyval2 DO -- pos 위치의 레코드 처리 pos = pos + 1; END WHILE; END IF;정렬 테이블 변수 수정 연산자 규칙
연산 동작 규칙 INSERT (위치 미지정) 정렬 순서를 유지하는 올바른 위치에 삽입 INSERT (위치 지정) 정렬 위반 여부 확인 → 위반 시 오류 발생 UPDATE / 셀 대입 검색 키 컬럼 수정 불가 / 존재하지 않는 레코드 수정 불가 Primary Key 정의된 경우 모든 연산에서 유일성 검사 제한 사항 (Limitations)
- 검색 키에 지원되지 않는 타입: Spatial data types, LOB types
- 테이블 함수(Table Function)의 출력은 정렬 테이블 타입으로 정의 불가
4. 8.3 Auto Type Derivation (자동 타입 추론)
변수의 타입을 명시하지 않고 SQLScript가 자동으로 타입을 결정하도록 하는 기능. 스칼라 변수, 테이블 변수, 배열에 모두 사용 가능하다.문법 (Syntax)
-- 스칼라 AUTO 변수 DECLARE <sql_identifier> [{, <sql_identifier>}...] [CONSTANT] AUTO [NOT NULL] <proc_default> -- 테이블 AUTO 변수 DECLARE <sql_identifier> [{, <sql_identifier>}...] [CONSTANT] AUTO <proc_table_default>⚠️ 주의 DEFAULT 값은 필수이며 생략할 수 없다.예제
declare var1 auto = 1.0; -- DECIMAL 타입으로 추론 declare arr1 auto = array(1, 2); -- INTEGER ARRAY로 추론 declare tab1 auto = select 1 as x from dummy; -- TABLE(x INT)로 추론타입 추론 규칙 (Data Type Derivation)
기본값의 타입을 기반으로 추론되지만, 길이가 있는 경우 최대 길이(MAX_LENGTH)를 사용한다.
실제 기본값 타입 추론되는 AUTO 변수 타입 VARCHAR(n) VARCHAR(MAX_LENGTH) NVARCHAR(n) NVARCHAR(MAX_LENGTH) ALHPANUM(n) ALPHANUM(MAX_LENGTH) VARBINARY(n) VARBINARY(MAX_LENGTH) DECIMAL(p, s) DECIMAL SMALLDECIMAL DECIMAL ⚠️ Caution — 비호환성 주의AUTO가 키워드로 처리되므로, 기존에AUTO라는 이름의 테이블/타입을 사용하던 코드에 문제가 발생할 수 있다.
회피 방법:SCHEMA.AUTO또는"AUTO"(따옴표) 형식으로 사용.
예시:-- 비호환 예시 create table auto (a bigint); declare tab1 auto = select 1 a, 2 b from dummy; -- 오류! -- 회피 방법 do begin declare tab1 "AUTO"; -- 따옴표 사용 declare tab2 schema_x.auto; -- schema.table_name 사용 end;AUTO 타입 제한 사항 (Scope and Limitations)
- 트리거(trigger) 내부에서는 사용 불가
- Row-type 변수에는 사용 불가
- 기본값이 다음을 포함하는 경우 사용 불가:
- 시스템 변수 (system variables)
- 테이블 또는 auto-type 테이블의 스칼라 접근
'SAP' 카테고리의 다른 글
ABAP 정규식 빌더 (0) 2026.06.02 SAP HANA SQLScript - Built-in Libraries (12.2 ~ 12.3) (0) 2026.05.30 SAP HANA SQL — 4.12 Error Codes (0) 2026.05.29 SAP HANA SQL - 4.5 Operators / 4.6 Expressions (0) 2026.05.29 AMDP 없이 CDS 데이터 구성하기 | SAP ABAP (0) 2026.05.29 - 로컬 변수는