假设我有一个表示层次结构的数据库表,其中包含以下列:

  • id
  • predecessor_id
  • 名称

  • 从给定的ID开始,我必须能够检索所有子节点(不仅是直接子节点)。由于ABAP中没有公用表表达式(WITH RECURSIVE),因此解决此问题的最佳方法是什么?

    我想到的一种可能的解决方案是遍历结果集(LOOP或使用游标),然后递归调用一个检索直接子节点的函数。但是,我希望有一种更优雅的方法。

    最佳答案

    首先,您需要知道SAP不是数据库,而OpenSQL始终会转换为基础数据库的SQL方言。如果基础数据库不支持WITHWITH RECURSIVE,并且从下面的article中可以看出,并不是每个数据库都支持,那么将其添加到OpenSQL中就没有任何意义,因为在许多情况下将没有映射到。

    因此,第一个解决方案将是您所建议的,编写一个单独的递归函数/方法/子例程,或者如果您真的想使用基础数据库功能,则可以使用ADBC接口(interface)。如果您熟悉JDBC,那么这个概念对您来说不是一个新手。如果您出于生产目的这样做,则应确保将来数据库迁移的可能性很小或没有。

    带有ADBC的解决方案在具有底层Oracle数据库的SAP系统上适用于我。

    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( ).
    

    10-04 23:27