Меню

Упрощаем работу с ADBC

С переходом на платформу HANA все актуальнее становится писать различного рода отчеты/программы с помощью «родных» NATIVE запросов к БД HANA, ведь используя встроенные механизмы и функции можно получить значительное преимущество перед OPEN SQL. В данной статье я не планирую переписывать все то, что можно найти в SСN или других ресурсах, но лишь хочу поделиться маленькими секретами, которые могут помочь каждому, кто ежедневно прикладывает руки к клавиатуре ради ABAPа (особенно начинающим).

С переходом на платформу HANA все актуальнее становится писать различного рода отчеты/программы с помощью «родных» NATIVE запросов к БД HANA, ведь используя встроенные механизмы и функции можно получить значительное преимущество перед OPEN SQL. В данной статье я не планирую переписывать все то, что можно найти в SСN или других ресурсах, но лишь хочу поделиться маленькими секретами, которые могут помочь каждому, кто ежедневно прикладывает руки к клавиатуре ради ABAPа (особенно начинающим). Информация в целом будет затрагивать элементарные возможности ADBC и особенности работы с диапазонами (RANGES).

Начну я с того, что ABAP Database Connectivity (сокращенно ADBC) стал для меня в последнее время весьма частым инструментом. Если кто-то еще не в курсе, то это новый объектный класс-инструмент для запросов к БД, появился он в ABAP release 6.10, но как сообщают источники, был задокументирован только в ABAP release 7.20. И можно однозначно сказать: он намного удобнее прежнего NATIVE SQL, но, как говорится, мнение читателя может не совпадать с мнением автора. Референс по ADBC вы можете найти на официальной странице http://help-legacy.sap.com/abapdocu_702/en/abenadbc.htm

Для демонстрации работы ADBC кратко приведу простой сниппет с комментариями для выбора, скажем, всех заказов за определённый год по сбытовой организации (возьмем код 1000) в разрезе месяца, клиента и материала, вычисляя их сумму с помощью агрегатной функции SUM:

Пример №1. Программа выбора заказов:

TYPES: BEGIN OF T_VBAP,
      MONAT TYPE I,
      VKORG TYPE VBAK-VKORG,
      VTWEG TYPE VBAK-VTWEG,
      KUNNR TYPE VBAK-KUNNR,
      NAME1 TYPE KNA1-NAME1,
      MATNR TYPE VBAP-MATNR,
      ARKTX TYPE VBAP-ARKTX,
      NETSUM TYPE VBAP-NETWR,
      END OF T_VBAP.

DATA: LV_STATEMENT TYPE STRING.
DATA: LR_RESULT TYPE REF TO DATA.
DATA: LT_VBAP TYPE STANDARD TABLE OF T_VBAP.
DATA: LO_CONN TYPE REF TO CL_SQL_CONNECTION,
  LO_STATEMENT TYPE REF TO CL_SQL_STATEMENT,
  LO_RESULT_SET TYPE REF TO CL_SQL_RESULT_SET.

PARAMETERS: P_YEAR TYPE CHAR4,
            P_VKORG TYPE VKORG.

START-OF-SELECTION.
 

Получаем ссылку на таблицу, куда будем «складывать» результат:


GET REFERENCE OF LT_VBAP INTO LR_RESULT.
 

Пишем запрос:


LV_STATEMENT =
| SELECT MONTH(VBAK.AUDAT) AS MONAT, VBAK.VKORG,VBAK.VTWEG,VBAK.KUNNR,KNA1.NAME1,VBAP.MATNR,VBAP.ARKTX, |
&& | SUM(VBAP.NETWR) FROM VBAP |
&& | INNER JOIN VBAK ON VBAK.MANDT = VBAP.MANDT AND VBAK.VBELN = VBAP.VBELN |
&& | INNER JOIN KNA1 ON KNA1.MANDT = VBAP.MANDT AND VBAK.KUNNR = KNA1.KUNNR WHERE |
&& | VBAP.MANDT = '{ sy-mandt }' AND |
&& | VBAK.VKORG = '{ P_VKORG }'  AND  |
&& | YEAR(VBAK.AUDAT) =  '{ P_YEAR }' |
&& | GROUP BY MONTH(VBAK.AUDAT),VBAK.VKORG,VBAK.VTWEG,VBAK.KUNNR,KNA1.NAME1,VBAP.MATNR,VBAP.ARKTX |
&& | ORDER BY MONAT |.

TRY.

Получаем «коннект», создаем запрос, выполняем его и получаем весь результат в нашу таблицу:


  LO_CONN = CL_SQL_CONNECTION=>GET_CONNECTION( ).
  LO_STATEMENT = LO_CONN->CREATE_STATEMENT( ).
  LO_RESULT_SET = LO_STATEMENT->EXECUTE_QUERY( LV_STATEMENT ).
  LO_RESULT_SET->SET_PARAM_TABLE( LR_RESULT ).
  LO_RESULT_SET->NEXT_PACKAGE( ).
  LO_RESULT_SET->CLOSE( ).


CATCH CX_SQL_EXCEPTION.

  WRITE:/ 'Что-то пошло не так'.

ENDTRY.

  WRITE:/ 'Запрос выполнен'.

Кратко опишу использованные классы:

CL_SQL_CONNECTION – Класс для создания связи с БД.

CL_SQL_STATEMENT – Класс для выполнения операций SQL.

CL_SQL_PREPARED_STATEMENT – «родственник» класса CL_SQL_STATEMENT, позволяет создавать запросы с параметрами.

CL_SQL_RESULT_SET – Класс для обработки результатов запроса.

CX_SQL_EXCEPTION – Класс EXCEPTION.

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

UPTO    - max. Anzahl zu lesender Datensätze  (Знание немецкого языка не бывает бесполезным! )/ макс. Число данных для загрузки, т.е. число строк;

ROWS_RET - Anzahl gelesener Datensätze / число прочитанных строк.

Кстати, для того чтобы проверить запрос перед его вставкой в программу неплохо воспользоваться ST04 и поэксперементировать в редакторе SQL (Рис.1.):

Рис.1 ST04, Редактор SQL

Как видите, мы можем использовать массу преимуществ встроенных функций и выражений в HANA DB, используя такой подход, ведь даже используя элементарные функции для работы с датой и временем, а также весьма специфические для HANA DB, мы можем быстро формировать эффективные запросы для разработки отчетов любого типа. Но есть нюансы! А если нам нужны стандартные возможности работы, например, с RANGE (диапазонами)? Для этого можно использовать специальные классы для преобразования таблицы диапазонов в строку SQL, приведу два способа с помощью двух разных классов: с помощью класса CL_LIB_SELTAB и с помощью класса CL_SHDB_SELTAB.

Способ 1: Используем класс CL_LIB_SELTAB

Например, если мы зададим некую таблицу значений для выбора с именем S_VKORG, то можем «конвертировать» ее в готовую SQL строку для условия WHERE, используя данный код:

DATA: O_COND TYPE REF TO CL_LIB_SELTAB,
      H_HANDLE TYPE REF TO CL_ABAP_TABLEDESCR,
      L_COND TYPE STRING.

-----------------------------------------------

CALL METHOD CL_LIB_SELTAB=>NEW
   EXPORTING
     IT_SEL = S_VKORG[]
   RECEIVING
     RR_REF = O_COND.

CALL METHOD O_COND->SQL_WHERE_CONDITION
   EXPORTING
     IV_FIELD = 'VBAP.VKORG'
   RECEIVING
     RV_COND  = WHERE_STR_VKORG.
 

В зависимости от содержания получим разные условия (BETWEEN,IN, OR и тд), затем полученную строку можно смело вставить в наш SQL код для выборки (пример №1):

LV_STATEMENT =
| SELECT MONTH(VBAK.AUDAT) AS MONAT, VBAK.VKORG,VBAK.VTWEG,VBAK.KUNNR,KNA1.NAME1,VBAP.MATNR,VBAP.ARKTX, |
&& | SUM(VBAP.NETWR) FROM VBAP |
&& | INNER JOIN VBAK ON VBAK.MANDT = VBAP.MANDT AND VBAK.VBELN = VBAP.VBELN |
&& | INNER JOIN KNA1 ON KNA1.MANDT = VBAP.MANDT AND VBAK.KUNNR = KNA1.KUNNR WHERE |

&& | VBAP.MANDT = '{ sy-mandt }' AND |
&& | ( { WHERE_STR_VKORG } ) AND 
&& | YEAR(VBAK.AUDAT) =  '{ P_YEAR }' |
&& | GROUP BY MONTH(VBAK.AUDAT),VBAK.VKORG,VBAK.VTWEG,VBAK.KUNNR,KNA1.NAME1,VBAP.MATNR,VBAP.ARKTX |
&& | ORDER BY MONAT |.

Замечу, что при пустой таблице, значение будет что-то вроде «(VBAK.VKORG LIKE ‘%’)». Но не торопимся радоваться! Меня ждал неприятный сюрприз: дело в том, что метод может неправильно конвертировать наши RANGES, «сливая» ,например, значения HIGH и LOW в одно значение поля LOW, краткая иллюстрация (Рис 2.):

Рис 2. Содержание перменной после обработки классом CL_LIB_SELTAB

Согласитесь, неприятно! А все потому, что структура для конвертации представлена в классе так:

types:
    BEGIN OF ts_sel,
        sign(1)    TYPE c,
        option(2)  TYPE c,
        low(30)    TYPE c,
        high(30)   TYPE c,
     

Если хотите прочитать статью полностью и оставить свои комментарии присоединяйтесь к sapland

У вас уже есть учетная запись?

Войти

Обсуждения Количество комментариев3

Комментарий от  

Валерий Заузолков

  |  24 мая 2017, 13:46

Просто как статья про ADBC - отлично!
 
Только объясните, пожлста, след.момент: Если система на HANA, т.е. скорее всего базис будет 7.4, а м.б. и 7.5, соответственно, есть более удобный инструментарий - можно пользоваться новым синтаксисом Open SQL, CDS-view или AMDP, для вызова процедур или вьюшек созданных непосредственно в HANA (минуя ABAP-словарь), можно создавать прокси и вызывать через них.
Зачем ADBC в контексте HANA?
 
И, как мне кажется, к ADBC относятся те же рекомендации, что и к Native SQL - по возможности предпочитать Open SQL, в связи с тем, что NW оптимизирован под использование Open SQL.

Комментарий от  

Леонид Мартынов

  |  02 июня 2017, 11:41

Просто как статья про ADBC - отлично!
 
Только объясните, пожлста, след.момент: Если система на HANA, т.е. скорее всего базис будет 7.4, а м.б. и 7.5, соответственно, есть более удобный инструментарий - можно пользоваться новым синтаксисом Open SQL, CDS-view или AMDP, для вызова процедур или вьюшек созданных непосредственно в HANA (минуя ABAP-словарь), можно создавать прокси и вызывать через них.
Зачем ADBC в контексте HANA?
 
И, как мне кажется, к ADBC относятся те же рекомендации, что и к Native SQL - по возможности предпочитать Open SQL, в связи с тем, что NW оптимизирован под использование Open SQL.

Спасибо за отзыв!
 
Я согласен для HANA актуальна  HANA studio. Но я имел опыт с тем, что например доступ к ней разработчик по каким-либо причинам не имеет, а новый Open SQL не поддерживает всех возможностей, то при прочих равных удобно использовать ADBC со всеми плюсами сырого запроса к БД. То же касается и не HANA платформы, в любом случае цель была показать возможности ADBC! И большое вам спасибо за интерес к статье!

Комментарий от  

Данил Жакаев

  |  03 октября 2018, 01:04

Просто как статья про ADBC - отлично!
 
Только объясните, пожлста, след.момент: Если система на HANA, т.е. скорее всего базис будет 7.4, а м.б. и 7.5, соответственно, есть более удобный инструментарий - можно пользоваться новым синтаксисом Open SQL, CDS-view или AMDP, для вызова процедур или вьюшек созданных непосредственно в HANA (минуя ABAP-словарь), можно создавать прокси и вызывать через них.
Зачем ADBC в контексте HANA?
 
И, как мне кажется, к ADBC относятся те же рекомендации, что и к Native SQL - по возможности предпочитать Open SQL, в связи с тем, что NW оптимизирован под использование Open SQL.

ADBC нужен в основном для динамического SQL.
Так же через ADBC можно генерировать не только выборки, но и DDL.
 
Как пример, был опыт создания базового ABAP класса экстрактора из Calculation View из BW во внешние системы - в классе-наследнике просто указываешь в атрибут имя CV и переопределяешь метод для заполнения placeholders - и оно работает динамически.