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

Умови WHERE

Клаузула WHERE зустрічається у двох контекстах: ABAP SQL (запити до бази) і обробка внутрішніх таблиць (LOOP AT, READ TABLE, DELETE, FILTER). Синтаксис схожий, але можливості відрізняються: у SQL ширший набір операторів і підзапити, у internal tables — обмеження на типи і відсутність NULL.

Ця сторінка — коротка шпаргалка по операторах, формам запису і типових пастках. Для повного переліку дивись ABAP Keyword Documentation.

SQL-оператори порівняння

Section titled “SQL-оператори порівняння”

Базові: = (EQ), <> (NE), < (LT), > (GT), <= (LE), >= (GE). Комбінуються через AND, OR, NOT; дужки — для явного пріоритету.

SELECT carrid, connid, fltime
FROM zdemo_abap_flsch
WHERE carrid = 'LH'
AND ( fltime > 300 OR cityto = 'NEW YORK' )
AND connid <> '0400'
INTO TABLE @DATA(result).
" Діапазон
WHERE fltime BETWEEN 100 AND 300
" Шаблон: % — довільна послідовність, _ — один символ
WHERE cityfrom LIKE 'NEW%'
" ESCAPE — коли % або _ має бути літерально
WHERE animal LIKE '%#%' ESCAPE '#'
" Набір значень
WHERE carrid IN ( 'LH', 'AA', 'UA' )
" Кортежний IN — одночасна перевірка кількох колонок
WHERE ( id, animal ) IN ( ( 1, 'bear' ), ( 3, 'giraffe' ) )
" Підзапит у IN
WHERE carrid IN ( SELECT carrid FROM zdemo_abap_carr WHERE currcode = 'USD' )

ESCAPE у LIKE задає escape-символ довжиною 1: ESCAPE '#' означає, що #% і #_ у шаблоні трактуються буквально.

IN приймає range table — внутрішню таблицю зі стандартною структурою SIGN/OPTION/LOW/HIGH. Зручно для умов селекційного екрана або динамічної фільтрації:

DATA rangestab TYPE RANGE OF i.
rangestab = VALUE #( ( sign = 'I' option = 'BT' low = 1 high = 10 ) ).
SELECT id FROM @itab AS tab
WHERE count IN @rangestab
INTO TABLE @DATA(it).

SIGN: I (include) / E (exclude). OPTION: EQ/NE/LT/LE/GT/GE/BT (between)/NB/CP (contains pattern)/NP.

" Скалярний підзапит
WHERE count = ( SELECT key_field FROM zdemo_abap_tab1 WHERE num1 = 40 )
" Квантори ALL / ANY / SOME
WHERE count > ALL ( SELECT key_field FROM zdemo_abap_tab1 )
" Корелюючий підзапит із EXISTS
SELECT carrid, carrname
FROM zdemo_abap_carr AS c
WHERE EXISTS ( SELECT 'X' FROM zdemo_abap_flsch AS f
WHERE f~carrid = c~carrid )
INTO TABLE @DATA(carriers_with_flights).

У ABAP SQL WHERE валідні обидва предикати: IS [NOT] NULL і IS [NOT] INITIAL.

" NULL у результатах outer join або nullable CDS-полях
WHERE cityto IS NOT NULL
" Ініціальне значення типу колонки
WHERE count IS NOT INITIAL

WHERE-умову можна передати як символьний об’єкт або як внутрішню таблицю рядків:

" Один рядок
DATA(dyn_where) = `count > 15`.
SELECT id FROM @itab AS tab
WHERE (dyn_where)
INTO TABLE @DATA(it).

Таблиця рядків зручна для довгих умов — кожен елемент містить фрагмент (операнд, оператор, значення):

DATA(dyn_where_tab) = VALUE string_table(
( `animal = 'kangaroo'` )
( `OR` )
( `count = 4` ) ).
SELECT id FROM @itab AS tab
WHERE (dyn_where_tab)
INTO TABLE @DATA(it2).

WHERE у внутрішніх таблицях

Section titled “WHERE у внутрішніх таблицях”

Синтаксис схожий, але обмеженіший — тільки поля рядка таблиці, без підзапитів і без IS NULL (NULL в ABAP не існує як окреме значення). Натомість доступні символьні предикати (CO/CS/…) і предикати посилань (IS BOUND/IS INSTANCE OF).

" LOOP — обхід з фільтром
LOOP AT flights INTO DATA(fl) WHERE carrid = 'LH' AND fltime > 200.
" ...
ENDLOOP.
" DELETE — видалити відфільтровані
DELETE flights WHERE carrid = 'AA'.
" READ TABLE — знайти перший рядок за умовою
READ TABLE flights INTO DATA(first) WITH KEY carrid = 'LH'.
" FILTER — конструктор: новий стан з відфільтрованими рядками
DATA(lh_only) = FILTER #( flights WHERE carrid = 'LH' ).

Для рядкових/байтових полів доступні предикати, яких немає у “звичайному” WHERE:

ПредикатЗначення
CO (contains only)Містить тільки перелічені символи
CN (contains not only)Містить не тільки
CA (contains any)Містить будь-який з
NA (not any)Не містить жодного з
CS (contains string)Містить підрядок
NS (not string)Не містить підрядок
CP (covers pattern)Відповідає шаблону (* і +)
NP (no pattern)Не відповідає шаблону

Працюють у WHERE internal tables і у звичайних ABAP-виразах, не в SQL WHERE.

LOOP AT entries INTO DATA(e) WHERE code CP 'A+B*'.
" ...
ENDLOOP.

У WHERE для внутрішніх таблиць доступні також предикати для посилань:

LOOP AT refs INTO DATA(r) WHERE ref IS BOUND.
" ...
ENDLOOP.
LOOP AT refs INTO DATA(r2) WHERE ref IS INSTANCE OF zcl_special.
" ...
ENDLOOP.

Швидка таблиця “де що доступно”

Section titled “Швидка таблиця “де що доступно””
МожливістьSQL WHEREInternal table WHERE
=, <>, <, >, <=, >=тактак
BETWEEN, LIKE, IN (список/range)тактак
Підзапит у IN, EXISTS, ALL/ANY/SOMEтакні
IS [NOT] NULLтакні
IS [NOT] INITIALтактак
CO/CN/CA/NA/CS/NS/CP/NPнітак
IS BOUND / IS INSTANCE OFнітак
Динамічна умова ( <string|tab> )тактак

Адаптовано з 31_WHERE_Conditions.md (Apache 2.0). Повний перелік нюансів — в оригіналі.