Перейти до вмісту

Типи даних і функції SQLScript

Типи даних і функції SQLScript

Section titled “Типи даних і функції SQLScript”

Скалярні типи SAP HANA діляться на чотири категорії: рядки, дата/час, числа, бінарні. До кожної категорії — набір вбудованих SQL-функцій. Ця сторінка — швидкий лук-ап: який тип у яких сценаріях, які функції є, як конвертувати між форматами, на що звернути увагу.

ТипПризначенняРозмір
VARCHAR(n)ASCII / однобайтнийдо n байт
NVARCHAR(n)Unicode (UCS-2)до n символів
ALPHANUM(n)Алфавітно-цифровий, з лідуючими нулямидо n
SHORTTEXT(n)NVARCHAR з повнотекстовим індексомдо n
CLOBВеликий ASCII-текстдо 2 ГБ
NCLOBВеликий Unicode-текстдо 2 ГБ
TEXTNCLOB з повнотекстовим індексомдо 2 ГБ

⚠️ Грабля: VARCHAR vs NVARCHAR

У ABAP-ECC до S/4HANA текстові поля типу CHAR/STRING мапилися в VARCHAR. У S/4HANA та усіх нових об’єктах Unicode — стандарт, тому маєш бути NVARCHAR. Не плутай — VARCHAR('Jörg') не зламається, але ö у деяких налаштуваннях відображатиметься криво.

SELECT TO_VARCHAR(123) FROM dummy; -- '123'
SELECT TO_NVARCHAR(123) FROM dummy; -- N'123'
SELECT TO_VARCHAR(DATE'2024-12-31',
'DD.MM.YYYY') FROM dummy; -- '31.12.2024'
SELECT TO_INT('42') FROM dummy; -- 42
SELECT TO_DECIMAL('1.5', 10, 2) FROM dummy; -- 1.50
ФункціяЩо робить
LENGTH(s)К-сть символів
LCASE(s) / LOWER(s)У нижній регістр
UCASE(s) / UPPER(s)У верхній регістр
INITCAP(s)Перші літери слів — великі
LTRIM(s), RTRIM(s), TRIM(s)Прибирає пробіли
LPAD(s, n, c), RPAD(s, n, c)Доповнює до довжини n символом c
LEFT(s, n), RIGHT(s, n)Перші / останні n символів
SUBSTRING(s, start, length)Вирізає підрядок
LOCATE(s, substr)Позиція першого входження (0 якщо нема)
REPLACE(s, from, to)Заміна
CONCAT(a, b) або a || bКонкатенація
CONCAT_NAZ(a, b)Конкатенація з ігноруванням NULL
REPEAT(s, n)Повторити n разів
REVERSE(s)Перевернути
BINTOHEX(b), HEXTOBIN(s)Двійкові ↔ hex
SELECT firstname || ' ' || lastname AS name,
LPAD(TO_VARCHAR(id), 10, '0') AS padded_id,
SUBSTRING(title, 1, 50) AS short_title,
UPPER(LEFT(country, 3)) AS code
FROM users;
SELECT
LIKE_REGEXPR(text, '^[A-Z]\d+$') AS is_match,
LOCATE_REGEXPR('\d+' IN text) AS first_num_pos,
OCCURRENCES_REGEXPR('\d+' IN text) AS num_count,
REPLACE_REGEXPR('\s+' IN text WITH ' ') AS normalized,
SUBSTRING_REGEXPR('\d+' IN text) AS first_num
FROM logs;

Окрема бібліотека (з SAP HANA 2.0 SPS 04) для роботи з рядками — split, join, trim, format. Виклик через префікс:

DO BEGIN
USING sqlscript_string AS s;
DECLARE arr NVARCHAR(20) ARRAY;
arr := s:split('a,b,c,d', ','); -- розбити на елементи
SELECT * FROM UNNEST(:arr);
END;
ТипФорматРозмір
DATEYYYY-MM-DD4 байти
TIMEHH24:MI:SS4 байти
SECONDDATEYYYY-MM-DD HH24:MI:SS, точність до сек8 байт
TIMESTAMPYYYY-MM-DD HH24:MI:SS.FFFFFFF, точність до 100 нс8 байт

Літерали — з префіксом DATE, TIME, TIMESTAMP:

DATE'2024-12-31'
TIME'15:42:04.123'
TIMESTAMP'2024-12-31 23:59:59.999'

⚠️ Грабля: DATS != DATE

ABAP-тип DATS зберігається як VARCHAR(8) у форматі YYYYMMDD. Це рядок, не дата. У SQLScript віднімання двох DATS-полів того самого місяця дасть правильний результат випадково — як цілі числа. Як тільки місяці різні, віднімання обчислюється як арифметика рядків і дає сміття.

Перетворюй у DATE через TO_DATE(dats) перед арифметикою — і назад через TO_DATS(date) після, якщо треба зберегти.

TO_DATE('2024-12-31') -- з рядка (auto-detect)
TO_DATE('31=12=2024', 'DD=MM=YYYY') -- з кастомним форматом
TO_DATS(DATE'2024-12-31') -- DATE → 'YYYYMMDD' (для ABAP)
TO_DATE('20241231') -- '20241231' → DATE
TO_VARCHAR(CURRENT_DATE, 'DD.MM.YYYY')-- DATE → форматований рядок

Patterns для TO_VARCHAR:

PatternПриклад
YY24
YYYY2024
MM12
DD31
Q4 (квартал)
WW52 (тиждень року)
MONDEC
MONTHDECEMBER
RMXII (римські цифри)
DDD366 (день року)
ADD_DAYS(DATE'2024-01-31', 1) -- 2024-02-01
ADD_MONTHS(DATE'2024-01-31', 1) -- 2024-02-29 (round до останнього дня)
ADD_MONTHS_LAST(DATE'2024-02-28', 1) -- 2024-03-31 (last day → last day)
ADD_YEARS(DATE'2024-02-29', 1) -- 2025-02-28
ADD_WORKDAYS(d, n, 'CALID') -- з factory calendar
ADD_SECONDS(TIMESTAMP'...', 60)
DAYS_BETWEEN(d1, d2) -- різниця в днях
SECONDS_BETWEEN(t1, t2)
WORKDAYS_BETWEEN(d1, d2, 'CALID')
YEAR(d), QUARTER(d), MONTH(d), DAYOFMONTH(d),
WEEK(d), WEEKDAY(d), DAYOFYEAR(d),
HOUR(t), MINUTE(t), SECOND(t),
EXTRACT(YEAR FROM d), EXTRACT(MONTH FROM d) -- універсальний синтаксис
CURRENT_DATE -- DATE
CURRENT_TIME -- TIME
CURRENT_TIMESTAMP -- TIMESTAMP, локальний
CURRENT_UTCTIMESTAMP -- TIMESTAMP, UTC
NOW() -- те саме
LOCALTOUTC(ts, 'CET') -- з локальної у UTC
UTCTOLOCAL(ts, 'CET') -- з UTC у локальну
ТипКатегоріяДіапазон
TINYINTInteger0..255
SMALLINTInteger±32 767
INTEGERInteger±2 147 483 647
BIGINTInteger±9.2 × 10¹⁸
DECIMAL(p,s)Fixed-pointдо 38 цифр, s — знаки після коми
SMALLDECIMALDecimal floatingflexible, точно
DECIMAL без (p,s)Decimal floatingflexible, точно
REALBinary floating32 біти
DOUBLEBinary floating64 біти

⚠️ Грабля: REAL і DOUBLE — приблизні

TO_DOUBLE(1.2) - TO_DOUBLE(0.1) дає 1.0999999999999999, а не 1.1. Для грошових сум, кількостей, всього де важлива точність — використовуй DECIMAL. DOUBLE — для наукових/інженерних обчислень.

ФункціяПризначення
ABS(n)Модуль
SIGN(n)Знак: -1, 0, 1
UMINUS(n)Зміна знаку
MOD(a, b)Залишок від ділення
DIV(a, b)Цілочислове ділення
CEIL(n)Округлення вгору
FLOOR(n)Округлення вниз
ROUND(n, d)Округлення до d знаків
TRUNCATE(n, d)Усічення до d знаків
ФункціяПризначення
POWER(b, e)b у степені e
SQRT(n)Корінь квадратний
EXP(n)e^n
LN(n)Натуральний логарифм
LOG(b, n)Логарифм за основою b

SIN, COS, TAN, COT, ASIN, ACOS, ATAN, ATAN2(y,x), SINH, COSH, TANH. Аргументи — у радіанах.

SELECT RAND() FROM dummy; -- DOUBLE з [0..1), швидко
SELECT RAND_SECURE() FROM dummy; -- те саме, криптостійко

Грошові суми і кількості

Section titled “Грошові суми і кількості”

В HANA немає вбудованого звʼязку числового поля з валютою/одиницею — це робиться у CDS-аннотаціях або в коді. Для конвертацій:

CURRENCY_CONVERSION(
amount => 100,
source_unit => 'USD',
target_unit => 'EUR',
reference_date => CURRENT_DATE,
error_handling => 'set to null',
client => '100'
)
UNIT_CONVERSION(
quantity => 1000,
source_unit => 'KG',
target_unit => 'T',
error_handling => 'fail on error'
)

Беруть курси з таблиць TCURR/TCURX і одиниці з T006. Обовʼязково задається error_handling: fail on error, set to null, keep unconverted.

ТипПризначенняРозмір
VARBINARY(n)Послідовність байтівдо n байт
BLOBВеликий бінарникдо 2 ГБ
-- Літерал
x'FF AA 01' -- VARBINARY
-- Конвертації
BINTOHEX(x'FF') -- 'FF' (NVARCHAR)
HEXTOBIN('FF') -- x'FF'
TO_BLOB(x'FF') -- VARBINARY → BLOB
TO_VARBINARY('FF') -- з hex-рядка
BIT_AND(a, b) -- побітове І
BIT_OR(a, b) -- побітове АБО
BIT_XOR(a, b) -- виключне АБО
BIT_NOT(a) -- інверсія
BITCOUNT(a) -- к-сть встановлених бітів
BITSET(a, pos, bit) -- встановити біт
BITUNSET(a, pos) -- скинути біт
LENGTH(b) -- довжина в байтах

Універсальні конвертації

Section titled “Універсальні конвертації”

CAST — стандартний SQL:

CAST('123' AS INTEGER)
CAST(1.234 AS DECIMAL(10,2))
CAST(NULL AS DATE)

TO_* — HANA-специфічні, з опціональним форматом:

TO_INT(s), TO_BIGINT(s), TO_DECIMAL(s, p, s)
TO_DOUBLE(s), TO_REAL(s)
TO_DATE(s, fmt), TO_TIMESTAMP(s, fmt)
TO_VARCHAR(v, fmt), TO_NVARCHAR(v, fmt)
TO_BLOB(b), TO_CLOB(s), TO_NCLOB(s)
TO_BINARY(s), TO_VARBINARY(s)

⚠️ Грабля: TO_INT не падає

TO_INT('abc') повертає NULL, не помилку. Якщо хочеш hard-fail — обгортай у CASE з перевіркою на формат, або використовуй TRY_CAST (повертає NULL замість винятку — тобто навпаки, для безпечного приведення).

ФункціяПоведінка
COALESCE(a, b, c, ...)Перше не-NULL значення зі списку
IFNULL(a, b)Як COALESCE для двох аргументів
NULLIF(a, b)NULL якщо a = b, інакше a
NVL(a, b)Як IFNULL (Oracle-стиль)
SELECT COALESCE(team, dept, 'unassigned') AS group_name,
NULLIF(salary, 0) AS salary_or_null,
IFNULL(comment, '') || '!' AS commented
FROM users;