Как получить все дочерние узлы иерархической структуры в ABAP?

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

  • id
  • предшественник_ид
  • имя

Начиная с заданного идентификатора, я должен иметь возможность получать все дочерние узлы (а не только прямые дочерние узлы). Поскольку общие табличные выражения (WITH RECURSIVE) недоступны в ABAP, как лучше всего решить эту проблему?

Возможное решение, о котором я подумал, - это перебор набора результатов (LOOP или с помощью курсора) и рекурсивный вызов функции, которая извлекает прямые дочерние узлы. Однако я надеюсь, что есть более элегантный подход.


person Tudor Ciotlos    schedule 09.06.2016    source источник
comment
Я не вижу другого способа узнать всех потомков, кроме как рекурсивно выбирать потомков - именно то, о чем вы подумали. Там, где это было проблемой производительности, в некоторых случаях мы ввели столбец master_id, содержащий идентификатор верхнего уровня элемента и вторичный индекс в базе данных для него,   -  person rplantiko    schedule 14.06.2016
comment
Я не думаю, что это слишком широко, особенно с учетом того, что комментарий @ rplantiko является почти полным ответом.   -  person Wayne Conrad    schedule 07.07.2016


Ответы (1)


Прежде всего вам нужно знать, что SAP не является базой данных, а OpenSQL всегда переводится на диалект SQL базовой базы данных. Если базовая база данных не поддерживает WITH или WITH RECURSIVE и из того, что я вижу из следующей статьи, не каждая и каждая база данных делает это, то добавление ее в OpenSQL не имело бы никакого смысла, поскольку во многих случаях не было бы ничего, на что ее можно было бы сопоставить.

Итак, первое решение будет таким, как вы предложили, написав отдельную рекурсивную функцию / метод / подпрограмму, или, если вы действительно хотите использовать базовые функции базы данных, вы можете использовать интерфейс ADBC. Если вы знакомы с JDBC, то эта концепция не должна быть для вас новой. Однако, если вы делаете это для продуктивных целей, вам следует убедиться, что вероятность миграции базы данных в будущем мала или отсутствует.

Решение с ADBC, которое работает для меня в системе SAP с базовой базой данных Oracle.

REPORT Z_ADBC_TEST.

CLASS lcl_test DEFINITION.
    PUBLIC SECTION.
        CLASS-METHODS:
            main.
ENDCLASS.

CLASS lcl_test IMPLEMENTATION.
    METHOD main.
        DATA lo_sql_connection TYPE REF TO cl_sql_connection.
        DATA lo_sql_statement  TYPE REF TO cl_sql_statement.
        DATA lo_sql_result_set TYPE REF TO cl_sql_result_set.
        TYPES BEGIN OF lt_result_struct,
            n    TYPE i,
            fact TYPE i,
        END OF lt_result_struct.
        DATA lt_result TYPE TABLE OF t_result_struct WITH DEFAULT KEY.
        DATA lr_ref_to_data TYPE REF TO data.
        FIELD-SYMBOLS <fs_result> LIKE LINE OF lt_result.

        lo_sql_connection = cl_sql_connection=>get_connection( ).
        lo_sql_statement = lo_sql_connection->create_statement( ).
        GET REFERENCE OF lt_result INTO lr_ref_to_data.
        lo_sql_result_set = lo_sql_statement->execute_query(
            `WITH temp(n, fact) ` &&
            `AS (SELECT 0,1 FROM dual UNION ALL ` &&
            `SELECT n+1,(n+1)*fact FROM temp ` &&
            `WHERE n < 9) ` &&
            `SELECT * FROM temp`
        ).
        lo_sql_result_set->set_param_table( lr_ref_to_data ).
        WHILE lo_sql_result_set->next_package( ) > 0.
            LOOP AT lt_result ASSIGNING <fs_result>.
                WRITE: / <fs_result>-n, <fs_result>-fact.
            ENDLOOP.
        ENDWHILE.
    ENDMETHOD.
ENDCLASS.

END-OF-SELECTION.
    lcl_test=>main( ).
person Martin    schedule 13.06.2016
comment
Я не утверждал, что SAP - это база данных. Также у меня уже есть решение, использующее рекурсивный подход. Вопрос был в том, можно ли решить эту проблему по-другому. - person Tudor Ciotlos; 13.06.2016
comment
@TudorCiotlos Из чистого любопытства ... На какой СУБД построена ваша система SAP? - person Jagger; 14.06.2016
comment
@Jagger РСУБД в системе SAP, над которой я сейчас работаю, - это Oracle 11.2. - person Tudor Ciotlos; 14.06.2016
comment
@TudorCiotlos Тогда решение с использованием ADBC может быть полезным, если вы, например, столкнетесь с проблемами с производительностью, если иерархия станет более сложной и получит больше уровней. Если вы знаете, что он останется маленьким, то решение с собственной рекурсивной функцией, безусловно, лучше и надежнее. - person Jagger; 14.06.2016