Внутренние таблицы как источник в SQL запросах

В релизе ABAP 7.52 стало возможным использование внутренних таблиц как источника данных в ABAP SQL:

Существует два сценария выполнения таких запросов:

  • Для выполнения SQL запроса не требуется переноса содержимого внутренней таблицы на уровень СУБД. В таком случае обработка запроса осуществляется непосредственно на сервере приложений, по аналогии с табличным буфером.
  • Для выполнения SQL запроса требуется перенести содержимое внутренней таблицы во временную таблицу на уровень СУБД. Этот сценарий поддерживается не всеми СУБД и чтобы статический анализ кода не ругался, следует использовать прагму: ##itab_db_select. При отсутствии поддержки система выдаст исключение в runtime — CX_SY_SQL_UNSUPPORTED_FEATURE.

Разберём текущие особенности использования этих сценариев.

Основным предназначением данного синтаксиса безусловно является использование внутренней таблицы и JOIN её данных с данными в СУБД. По сути это еще одна альтернатива FOR ALL ENTRIES, но без тех ограничений что есть в FAE.

Использовать этот синтаксис как замену операций READ TABLE и LOOP в первом сценарии допустимо, но как правило выполняться это будет медленнее. Говоря о первом сценарии следует упомянуть что условия, по которым система решает следует ли переносить таблицу на уровень СУБД аналогичны тем условиям, что используются для определения необходимости обращения к СУБД при использовании буферизированных таблиц. Таким образом таблица будет переносится на уровень СУБД если:

  • Используются агрегатные функции,
  • Используется DISTINCT,
  • Используются JOIN-ы,
  • Используется WITH,
  • Используются SQL выражения не из списка совместимых,
  • Множество других ограничений…

Убедиться в том что таблица переносится в СУБД можно посмотрев трассировку запроса, выглядеть это будет примерно следующим образом:

Есть ряд особенностей SQL запросов с внутренней таблицей как источником данных:

  • Нельзя указать более одной таблицы в SQL запросе, JOIN двух внутренних таблиц сделать не выйдет. Нельзя использовать одну и ту же таблицу в запросе несколько раз, например с дополнением WITH.
  • Обязательно требуется указание псевдонима для внутренней таблицы через дополнение AS.
  • Тип строки таблицы может быть как элементарным, так и структурным:
    • Если строка элементарного типа, обращаться к столбцу этой таблицы можно через table_line. В списке полей для table_line можно задать псевдоним через AS. Тип таблицы в данном случае не может быть строкой (допустимо использование строк ссылающихся на словарный тип SSTRING) или ссылочным типом.
    • Если строка структурного типа, недопустимо обращение в SQL запросе к полям являющимися вложенными структурами, строками или таблицами.
  • Если используется дополнение ORDER BY PRIMARY KEY во внутренней таблице обязательно должен быть указан primary key.
  • Нельзя при статическом указании таблицы во FROM использовать обобщённые типы таблиц (вроде INDEX TABLE). Обобщённые типы могут быть использованы при динамическом FROM. Пример:
  • Внутренняя таблица не может содержать столбцов со ссылкой на устаревшие типы данных: DF16_SCL и DF34_SCL.
  • Если внутренняя таблица имеет элементарный тип, при использовании CTE, после WITH нельзя указывать поля через * или data_source~*.
  • Для внутренней таблицы необходимо указывать primary key явным образом, при использовании стандартного ключа (with default key) система выдаст предупреждение.

Даже если таблица не будет перенесена на уровень СУБД, данные в ней обрабатываются так как же как и в СУБД:

  • Строки со ссылкой на SSTRING обрабатываются как строки с фиксированной длинной и игнорированием завершающих пробелов.
  • SQL выражения работают таким же образом, как если бы они работали на уровне СУБД:
    • DIV и MOD могут выдавать отличные от аналогичных в ABAP результаты
    • Обработка NULL значений аналогична тому как это работает в SQL запросах.
  • Таблица всегда рассматривается как независимая от манданта.

Примеры

Следующий пример демонстрирует типичный случай использования внутренних таблиц как источника данных, а именно перенос таблицы на уровень СУБД и выполнение JOIN:

Пример в котором не происходит обращения к СУБД:

Формирование результата элементарного типа (lt_result1) и структурного (lt_result2):

Производительность

Если сравнивать скорость выполнения FAE с FDA и JOIN с внутренней таблицей, скорость работы практически не отличается, оба сценария выигрывают у сценария переноса внутренней таблицы через AMDP.

Итого

Подводя итоги, данный механизм выглядит вполне привлекательной заменой использования запросов с FOR ALL ENTRIES, если сравнивать с точки зрения накладываемых в обоих случаях ограничений и безопасности в части необходимости доп. проверок в коде при использовании FAE.

1 комментарий

  1. Спасибо за статью.
    Если нужно сделать агрегацию внутренней таблицы то агрегация через передачу во временную таблицу на БД тоже будет работать медленней чем через loop/collect?
    Например таблица 100к записей, которая становится 5к после агрегации.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *