Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
thomas_jung
Developer Advocate
Developer Advocate
74,812

Introduction

In this first edition of this HANA Developer's Journey I barely scratched the surface on some of the ways which a developer might begin their transition into the HANA world. Today I want to describe a scenario I've been studying quite a lot in the past few days: accessing HANA from ABAP in the current state.  By this, I mean what can be built today.  We all know that SAP has some exciting plans for ABAP specific functionality on top of HANA, but what everyone might not know is how much can be done today when HANA runs as a secondary database for your current ABAP based systems.  This is exactly how SAP is building the current HANA Accelerators, so it’s worth taking a little time to study how these are built and what development options within the ABAP environment support this scenario.

HANA as a Secondary Database

The scenario I'm describing is one that is quite common right now for HANA implementations.  You install HANA as a secondary database instead of a replacement for your current database.  You then use replication to move a copy of the data to the HANA system. Your ABAP applications can then be accelerated by reading data from the HANA copy instead of the local database. Throughout the rest of this blog I want to discuss the technical options for how you can perform that accelerated read.

ABAP Secondary Database Connection

ABAP has long had the ability to make a secondary database connection.  This allows ABAP programs to access a database system other than the local database. This secondary database connection can even be of a completely different DBMS vendor type. This functionality is extended to support SAP HANA for all the NetWeaver release levels from 7.00 and beyond. Service Note 1517236 (for SAP Internal) 1597627 (for everyone) lists the preconditions and technical steps for connection to HANA systems and should always be the master guide for these preconditions, however I will summarize the current state at the time of publication of this blog.

Preconditions

  • SAP HANA Client is installed on each ABAP Application Server. ABAP Application Server Operating System must support the HANA Client (check Platform Availability Matrix for supported operating systems).
  • SAP HANA DBSL is installed (this is the Database specific library which is part of the ABAP Kernel)
  • The SAP HANA DBSL is only available for the ABAP Kernel 7.20
    • Kernel 7.20 is already the kernel for NetWeaver 7.02, 7.03, 7.20, 7.30 and 7.31
    • Kernel 7.20 is backward compatible and can also be applied to NetWeaver 7.00, 7.01, 7.10, and 7.11
  • Your ABAP system must be Unicode or Single Code Page 1100 (Latin 1/ISO-8850-1) -See Service note 1700052 for non-Unicode Support instructions

Next, your ABAP system must be configured to connect to this alternative database. You have one central location where you maintain the database connection string, username and password.  Your applications then only need to specify the configuration key for the database making the connection information application independent.

This configuration can be done via table maintenance (Transaction SM30) for table DBCON. From the configuration screen you supply the DBMS type (HDB for HANA), the user name and password you want to use for all connections and the connection string. Be sure to include the port number for HANA systems. It should be 3<Instance Number>15. So if your HANA Database was instance 01, the port would be 30115.

DBCON can also be maintained via transaction DBACOCKPIT. Ultimately you end up with the same entry information as DBCON, but you get a little more information (such as the default Schema) and you can test the connection information from here.

Secondary Database Connection Via Open SQL

The easiest solution for performing SQL operations from ABAP to your secondary database connection is to use the same Open SQL statements which ABAP developers are already familiar with. If you supply the additional syntax of CONNECTION (dbcon), you can force the Open SQL statement to be performed against the alternative database connection. 

For instance, let’s take a simple Select and perform it against our HANA database:

  SELECT * FROM sflight CONNECTION ('AB1')
    INTO TABLE lt_sflight
   WHERE carrid = 'LH'.

The advantage of this approach is in its simplicity.  With one minor addition to existing SQL Statements you can instead redirect your operation to HANA. The downside is that the table or view you are accessing must exist in the ABAP Data Dictionary. That isn't a huge problem for this Accelerator scenario considering the data all resides in the local ABAP DBMS and gets replicated to HANA. In this situation we will always have local copies of the tables in the ABAP Data Dictionary.  This does mean that you can't access HANA specific artifacts like Analytic Views or Database Procedures. You also couldn't access any tables which use HANA as their own/primary persistence.

Secondary Database Connection Via Native SQL

ABAP also has the ability to utilize Native SQL. In this situation you write you database specific SQL statements.  This allows you to access tables and other artifacts which only exist in the underlying database.  There is also syntax in Native SQL to allow you to call Database Procedures.  If we take the example from above, we can rewrite it using Native SQL:

EXEC SQL.
    connect to 'AB1' as 'AB1'
  ENDEXEC.
  EXEC SQL.
    open dbcur for select * from sflight where mandt = :sy-mandt and carrid = 'LH'
  ENDEXEC.
  DO.
    EXEC SQL.
      fetch next dbcur into :ls_sflight
    ENDEXEC.
    IF sy-subrc NE 0.
      EXIT.
    ELSE.
      APPEND ls_sflight TO lt_sflight.
    ENDIF.
  ENDDO.
  EXEC SQL.
    close dbcur
  ENDEXEC.
  EXEC SQL.
    disconnect 'AB1'
  ENDEXEC.

Its certainly more code than the Open SQL option and a little less elegant because we are working with database cursors to bring back an array of data.  However the upside is access to features we wouldn't have otherwise. For example I can insert data into a HANA table and use the HANA database sequence for the number range or built in database functions like now().

    EXEC SQL.
      insert into "REALREAL"."realreal.db/ORDER_HEADER"
       values("REALREAL"."realreal.db/ORDER_SEQ".NEXTVAL,
                   :lv_date,:lv_buyer,:lv_processor,:lv_amount,now() )
    ENDEXEC.
    EXEC SQL.
      insert into "REALREAL"."realreal.db/ORDER_ITEM" values((select max(ORDER_KEY)
        from "REALREAL"."realreal.db/ORDER_HEADER"),0,:lv_product,:lv_quantity,:lv_amount)
    ENDEXEC.

The other disadvantage to Native SQL via EXEC SQL is that there are little to no syntax checks on the SQL statements which you create. Errors aren't caught until runtime and can lead to short dumps if the exceptions aren't properly handled.  This makes testing absolutely essential.

Secondary Database Connection via Native SQL - ADBC

There is a third option that provides the benefits of the Native SQL connection via EXEC SQL, but also improves on some of the limitations.  This is the concept of ADBC - ABAP Database Connectivity.  Basically it is a series of classes (CL_SQL*) which simplify and abstract the EXEC SQL blocks. For example we could once again rewrite our SELECT * FROM SFLIGHT example:

****Create the SQL Connection and pass in the DBCON ID to state which Database Connection will be used
  DATA lr_sql TYPE REF TO cl_sql_statement.
  CREATE OBJECT lr_sql
    EXPORTING
      con_ref = cl_sql_connection=>get_connection( 'AB1' ).
****Execute a query, passing in the query string and receiving a result set object
  DATA lr_result TYPE REF TO cl_sql_result_set.
  lr_result = lr_sql->execute_query(
    |SELECT * FROM SFLIGHT WHERE MANDT = { sy-mandt } AND CARRID = 'LH'| ).
****All data (parameters in, results sets back) is done via data references
  DATA lr_sflight TYPE REF TO data.
  GET REFERENCE OF lt_sflight INTO lr_sflight.
****Get the result data set back into our ABAP internal table
  lr_result->set_param_table( lr_sflight ).
  lr_result->next_package( ).
  lr_result->close( ).

Here we at least remove the step-wise processing of the Database Cursor and instead read an entire package of data back into our internal table at once.  By default the initial package size will return all resulting records, but you can also specify any package size you wish thereby tuning processing for large return result sets.  Most importantly for HANA situations, however, is that ADBC also lets you access non-Data Dictionary artifacts including HANA Stored Procedures.  Given the advantages of ADBC over EXEC SQL, it is SAP's recommendation that you always try to use the ADBC class based interfaces.

Closing

This is really just the beginning of what you could with this Accelerator approach to ABAP integration into SAP HANA. I've used very simplistic SQL statements in my examples on purpose so that I could instead focus on the details of how the technical integration works.  However, the real power comes when you execute more powerful statements (SELECT SUM ... GROUP BY), access HANA specific artifacts (like OLAP Views upon OLTP tables), or database procedures.  These are all topics which I will explore more in future editions of this blog.

176 Comments
justin_molenaur2
Contributor
0 Kudos

Thomas, thanks for the prompt response. Maybe I wasn't so clear.

I am trying to use a sidecar HANA instance as the secondary DB from an ABAP system. Since the cluster table (BSEG) becomes a transparent table once it lands in HANA, I was under the impression that using the CONNECTION addition would allow a join using any table because of the previous point that all tables are transparent within HANA.

Since the secondary DB might not necessarily be an ABAP based system, it wouldn't really be possible to know if it was a cluster table or not, is that correct?

Many thanks,

Justin

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

TThe thing is that when you use openSQL even with CONNECTION, the metadata from the ABAP DDIC is still used. This is why it only works for tables that also exist on ABAP. Therefore the database connection will always think this is still a pool/cluster table. If you want to by pass this, you will need to use native SQL instead of openSQL.

justin_molenaur2
Contributor
0 Kudos

You beat me to it :smile: reading more closely I see that exact same point in your blog (and in multiple responses), I really need to read more closely....

I was considering the use of the native SQL option, however when building the dynamic SQL you would also have to somehow handle ranges in existing SQL code within the WHERE clause, which openSQL does very well without any real effort. Is there a recommended method to dynamically build the where clause based on ranges that may or may not be populated when using the native SQL method?

Some ideas here, but just wanted to see if you had an opinion.

Push down SELECT-OPTIONS to HANA

Many thanks,

Justin

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

That's definitely something you give up once you move away from openSQL. Your going to have do something to handle select options yourself since that's pretty much a concept only of openSAP.  There isn't really anything I'm aware of directly in native SQL to support that. I know that when people try to use select-options in things like SQLScript they often write the select-options range table into a temporary table and then join it.

Former Member
0 Kudos

Hey Thomas,

Nice blog, apparently implemented something like this but here is a question... there is a maximum_connections input which means that the limit if set to 0 then subsequently sets the maximum to 255.

This seems like it would be an issue currently... not sure on why that is even a thing if secondary DB for HANA is a valid option. Definitely the connection works fine and can be conveniently / dynamically switched out with the ADBC classes otherwise...

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

I don't think the maximum_connections is anything to worry about. People often compare it to the number of users on their system and that's incorrect.  There is a connection pool and connections are only used while actually communicating to the database. Therefore you can support a very high number of users with a much smaller number of maximum connections.

Former Member
0 Kudos

If the options of using the HANA as a primary or secondary DB is ruled out by the customer, but still they want to use the UI5 as a front end and Netweaver Gateway as a web service, the usage of stored procedures and AMDP is ruled out. Will the usage of logical databases in the Netweaver gateway server as this might be a performance booster? If not what will be the ideal approach?

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

Well your question really doesn't have anything to do with this blog. If you just have a general question about logical databases in ABAP, I would post that in the ABAP forum.  However from my background I would say that I was never a fan of Logical Database. They generally decrease performance because they often must do a lot of unnecessary SQL to reach the lower objects in a hierarchy. If HANA is not an option, than just writing good, clean Open SQL in ABAP is probably the best performance option.

UweFetzer_se38
Active Contributor
0 Kudos

And Logical Databases are obsolete since, don't know, 10(?) years...

Please don't use them anymore.

Former Member
0 Kudos

Thank you Thomas and Uwe Fetzer for your valuable input.

former_member223777
Discoverer
0 Kudos

Hi Thomas,

Do you have any solution to use HANA connection on standard SQVI Abap SQL?

We developed a custom data browser that running on HDB (ZSE16), the results are really perfect and imagine same benefit on sqvi..

zse16 code is below :smile:

*&---------------------------------------------------------------------*

*& Report  ZBC_DATA_BROWSER

*&

*&---------------------------------------------------------------------*

*&

*&

*&---------------------------------------------------------------------*

report  zbc_data_browser.

set extended check off.

type-pools: rsds.

tables zbc_data_browser.

data: begin of gt_htables occurs 1,

       table_name(30),

end of gt_htables.

data: gs_x030l  type x030l,

       gt_dfies  type table of dfies,

       gs_dfies  type dfies,

       gt_fdiff  type table of field_dif,

       gs_fdiff  type field_dif,

       gt_ftab   like table of rsdsfields with header line,

       gt_fcode  like table of rsdsfcode with header line,

       gt_events like table of rsdsevents with header line.

data: gv_selid  type rsdynsel-selid,

       gt_tables type table of rsdstabs,

       gs_tables type rsdstabs,

*      gt_fields type table of rsdsfields with header line,

       gt_expr   type rsds_texpr,

       gt_ranges type rsds_trange,

*      gs_ranges type rsds_range,

       gt_where  type rsds_twhere,

       gs_where  type rsds_where,

       gv_active type i.

data: gt_content type ref to data,

       gt_modif   type ref to data,

       gt_fcat    type lvc_t_fcat,

       gs_pfkey   type rsdspfkey.

data: gv_fieldok,

       gv_dbcnt(30).

field-symbols: <itab> type standard table,

                <ntab> type standard table.

define table_error.

   message e398(00) with 'Table' p_table &1.

end-of-definition.

*---------------------- parameters ------------------------*

parameters: p_table type tabname obligatory                                 "table

                                  memory id dtb

                                  matchcode object dd_dbtb_16.

parameters p_rows type i default 1000.                                      "rows

selection-screen skip.

parameters p_conn as checkbox default 'X'.

at selection-screen.

   if p_table ne gs_x030l-tabname.

     if not p_conn is initial.

       if not zcl_hana_cnt_util=>con_name is initial.

         perform get_hana_tables.

         read table gt_htables with key table_name = p_table.

         if sy-subrc ne 0.

           table_error 'is not selectable for Hana DB'.

         endif.

       else.

         message e398(00) with 'Hana connection is not active'.

       endif.

     else.

       clear zcl_hana_cnt_util=>con_name.

     endif.

     call function 'DDIF_NAMETAB_GET'

       exporting

         tabname   = p_table

       importing

         x030l_wa  = gs_x030l

       tables

         dfies_tab = gt_dfies

       exceptions

         others    = 1.

     if gs_x030l is initial.

       table_error 'does not exist or is not active'.

     elseif gs_x030l-tabtype ne 'T'

       and  gs_x030l-tabtype ne 'J'.

       table_error 'is not selectable'.

     endif.

*   Prepare free selection on table

     clear: gt_ftab[], gt_tables[], gt_ftab, gt_tables, gv_fieldok.

     select * from zbc_data_browser where tablename = p_table.

       gt_ftab-tablename = zbc_data_browser-tablename.

       gt_ftab-fieldname = zbc_data_browser-fieldname.

       append gt_ftabclear gt_ftab.

     endselect.

     if sy-subrc eq 0gv_fieldok = 'X'endif.

     loop at gt_dfies into gs_dfies

                     where keyflag = 'X'

                       and fieldname ne 'MANDT'

                       and fieldname ne 'MANDANT'

                       and fieldname ne 'CLIENT'

                       and rollname ne 'MANDT'.

       gs_tables-prim_tab = p_table.

       append gs_tables to gt_tables.

       if gv_fieldok is initial.

         gt_ftab-tablename = p_table.

         gt_ftab-fieldname = gs_dfies-fieldname.

         append gt_ftab.

       endif.

     endloop.

     clear: gv_selid.

   endif.

*------------------------- start of selection -------------------------*

start-of-selection.

   if gv_selid is initial.

*   Init free selection dialog

     gt_events-event = '5'.

     gt_events-prog = sy-cprog.

     gt_events-form 'NUMBER_OF_ENTRIES'.

     append gt_eventsclear gt_events.

     call function 'FREE_SELECTIONS_INIT'

       exporting

         expressions  = gt_expr

       importing

         selection_id = gv_selid

         expressions  = gt_expr

       tables

         events       = gt_events[]

         tables_tab   = gt_tables

         fields_tab   = gt_ftab[]

       exceptions

         others       = 1.

   endif.

   gs_pfkey-pfkey = 'MAIN1'.

   gs_pfkey-program = sy-cprog.

   gt_fcode-fcode = 'NUMB'.

   gt_fcode-form = 'NUMBER_OF_ENTRIES'.

   append gt_fcodeclear gt_fcode.

   call function 'FREE_SELECTIONS_DIALOG'

     exporting

       selection_id            = gv_selid

       title                   = 'Alan seçimleri'

       status                  = 1

       pfkey                   = gs_pfkey

     importing

       expressions             = gt_expr

       field_ranges            = gt_ranges

       number_of_active_fields = gv_active

     tables

       fields_tab              = gt_ftab[]

       fcode_tab               = gt_fcode[]

     exceptions

       internal_error          = 1

       no_action               = 1

       selid_not_found         = 1

       illegal_status          = 1.

   check sy-subrc eq 0.

   perform list.

*&---------------------------------------------------------------------*

*&      Form  list

*&---------------------------------------------------------------------*

form list.

   delete from zbc_data_browser where tablename = p_table.

   loop at gt_ftab.

     zbc_data_browser-tablename = gt_ftab-tablename.

     zbc_data_browser-fieldname = gt_ftab-fieldname.

     modify zbc_data_browserclear zbc_data_browser.

   endloop.

   perform f_create_table using p_table.

   perform f_select_table.

   perform f_display_table.

endform.                    "list

*&---------------------------------------------------------------------*

*&      Form  exit

*&---------------------------------------------------------------------*

form exit.

   exit.

endform.                    "exit

*---------------------------------------------------------------------*

*       FORM f_create_table                                           *

*---------------------------------------------------------------------*

form f_create_table using p_tabname.

   field-symbols: <l_fcat> type lvc_s_fcat.

   call function 'LVC_FIELDCATALOG_MERGE'

     exporting

       i_structure_name = p_tabname

     changing

       ct_fieldcat      = gt_fcat

     exceptions

       others           = 1.

   if sy-subrc = 0.

*   Complete field catalog

     loop at gt_fcat assigning <l_fcat>.

       <l_fcat>-tabname = p_tabname.

     endloop.

     call function 'LVC_FIELDCAT_COMPLETE'

       changing

         ct_fieldcat = gt_fcat

       exceptions

         others      = 1.

   else.

     write: 'Error building field catalog'.

     stop.

   endif.

* Create dynamic table for data

   call method cl_alv_table_create=>create_dynamic_table

     exporting

       it_fieldcatalog = gt_fcat

     importing

       ep_table        = gt_content.

   if sy-subrc = 0.

     assign gt_content->* to <itab>.

   else.

     write: 'Error creating internal table'.

     stop.

   endif.

* Create dynamic table for modif

   call method cl_alv_table_create=>create_dynamic_table

     exporting

       it_fieldcatalog = gt_fcat

     importing

       ep_table        = gt_modif.

   if sy-subrc = 0.

     assign gt_modif->* to <ntab>.

   else.

     write: 'Error creating internal table'.

     stop.

   endif.

endform.                    "f_create_table

*---------------------------------------------------------------------*

*       FORM f_select_table                                           *

*---------------------------------------------------------------------*

form f_select_table.

   if gv_active = 0.

     select * from (p_table)

              into corresponding fields of table <itab>

                up to p_rows rows

        connection (zcl_hana_cnt_util=>con_name).

   else.

*   Selection with parameters

     clear gt_where.

     call function 'FREE_SELECTIONS_RANGE_2_WHERE'

       exporting

         field_ranges  = gt_ranges

       importing

         where_clauses = gt_where.

     read table gt_where into gs_where with key tablename = p_table.

     select * from (p_table)

              into corresponding fields of table <itab>

                up to p_rows rows

        connection (zcl_hana_cnt_util=>con_name)

             where (gs_where-where_tab).

   endif.

   write sy-dbcnt to gv_dbcnt.

   shift gv_dbcnt left deleting leading: '0', space.

   concatenate 'Records:'(001) gv_dbcnt

          into gv_dbcnt separated by space.

   concatenate sy-title gv_dbcnt

          into sy-title separated by '       '.

   if sy-dbcnt = 0.

     write: 'No record selected'.

     stop.

   endif.

endform.                    "f_select_table

*&---------------------------------------------------------------------*

*&      Form  number_of_entries

*&---------------------------------------------------------------------*

form number_of_entries tables pt_rsseldyn structure rsseldyn

                               pt_rsdsfldnum structure rsdsfldnum

                         using p_fcode type rsdsfcode-fcode. "#EC *

   data: ls_rsseldyn type rsseldyn,

         ls_ranges like line of gt_ranges,

         ls_frange like line of ls_ranges-frange_t,

         ls_selopt type rsdsselopt.

   clear: gt_ranges, gt_where, gs_where,

          gs_where-where_tab[], gv_active.

   loop at pt_rsseldyn into ls_rsseldyn.

     if ls_rsseldyn-sign ne space.

       ls_ranges-tablename = ls_rsseldyn-tablename.

       ls_frange-fieldname = ls_rsseldyn-fieldname.

       ls_selopt-sign = ls_rsseldyn-sign.

       ls_selopt-option = ls_rsseldyn-option.

       ls_selopt-low = ls_rsseldyn-low.

       ls_selopt-high = ls_rsseldyn-high.

       append ls_selopt to ls_frange-selopt_tclear ls_selopt.

       append ls_frange to ls_ranges-frange_tclear ls_frange.

       append ls_ranges to gt_rangesclear ls_ranges.

       add 1 to gv_active.

     endif.

   endloop.

   delete adjacent duplicates from gt_ranges comparing all fields.

   if gv_active = 0.

     select count(*) from (p_table)

       connection (zcl_hana_cnt_util=>con_name).

   else.

*   Selection with parameters

     call function 'FREE_SELECTIONS_RANGE_2_WHERE'

       exporting

         field_ranges  = gt_ranges

       importing

         where_clauses = gt_where.

     read table gt_where into gs_where with key tablename = p_table.

     select count(*) from (p_table)

       connection (zcl_hana_cnt_util=>con_name)

            where (gs_where-where_tab).

   endif.

   write sy-dbcnt to gv_dbcnt.

   shift gv_dbcnt left deleting leading: '0', space.

   concatenate 'Records:'(001) gv_dbcnt

          into gv_dbcnt separated by space.

   message gv_dbcnt type 'I'.

   clear: pt_rsseldyn[], pt_rsdsfldnum[], p_fcode.

endform.                    "number_of_entries

*---------------------------------------------------------------------*

*       FORM f_display_table                                          *

*---------------------------------------------------------------------*

form f_display_table.

   call function 'REUSE_ALV_GRID_DISPLAY_LVC'

     exporting

       i_structure_name = p_table

     tables

       t_outtab         = <itab>

     exceptions

       program_error    = 1

       others           = 2.

endform.                    "f_display_table

*---------------------------------------------------------------------*

*       FORM f_add_system                                             *

*---------------------------------------------------------------------*

form f_add_system using p_new type c.

   field-symbols: <l_irec> type any,

                  <l_upd>  type any.

   loop at gt_fdiff into gs_fdiff.

     read table gt_dfies into gs_dfies

                     with key fieldname = gs_fdiff-fieldname.

     loop at <ntab> assigning <l_irec>.

       assign component gs_fdiff-fieldname of structure <l_irec> to <l_upd>.

       if gs_dfies-datatype = 'CLNT'.

         <l_upd> = sy-mandt.

       else.

         case gs_dfies-rollname.

           when 'AENAM'.

             <l_upd> = sy-uname.

           when 'AEDAT' or 'LAEDA'.

             <l_upd> = sy-datum.

           when 'AETIM'.

             <l_upd> = sy-uzeit.

           when others.

         endcase.

       endif.

     endloop.

   endloop.

endform.                    "f_add_system

*&---------------------------------------------------------------------*

*&      Form  GET_HANA_TABLES

*&---------------------------------------------------------------------*

form get_hana_tables .

   clear: gt_htables[], gt_htables.

   try.

       "open hana db connection

       exec sql.

         connect to :zcl_hana_cnt_util=>con_name

       endexec.

       if sy-subrc <> 0.

         raise exception type cx_sy_native_sql_error.

       endif.

       "get hana db tables

       exec sql.

         open dbcur for

           select distinct table_name

             from M_CS_TABLES

            where schema_name = :zcl_hana_cnt_util=>con_name

              and table_name = :p_table

       endexec.

       do.

         exec sql.

           fetch next dbcur into :gt_htables

         endexec.

         if sy-subrc ne 0.

           exit.

         else.

           append gt_htablesclear gt_htables.

         endif.

       enddo.

       exec sql.

         close dbcur

       endexec.

       "get hana db views

       exec sql.

         open dbcur for

           select distinct view_name

             from VIEWS

            where schema_name = :zcl_hana_cnt_util=>con_name

              and view_name = :p_table

       endexec.

       do.

         exec sql.

           fetch next dbcur into :gt_htables

         endexec.

         if sy-subrc ne 0.

           exit.

         else.

           append gt_htablesclear gt_htables.

         endif.

       enddo.

       exec sql.

         close dbcur

       endexec.

       "close hana db connection

       exec sql.

         disconnect :zcl_hana_cnt_util=>con_name

       endexec.

     catch cx_sy_native_sql_error.

       message 'SQL error' type 'I'.

   endtry.

endform.                    " GET_HANA_TABLES

shounakm
Explorer
0 Kudos

Hello All,

We are using a HANA Sidecar setup. In HANA Studio I created a view joining FAGLFLEXA and BSEG with around 10 columns. I am able to preview data in the view.

Within ECC I created a view with the same set of columns so that I can use OpenSQL. But when I am trying to query the view using OpenSQL , I am getting the following error:

SQL error 258 when accessing table

Error Text of the Database: "insufficient privilege: Not authorized:

The schema has other views in it which is working fine. I believe some of the other tables and views that got replicated via the SLT had automatically granted the "select" rights on the schema.

What am I missing here or some other approach is required. Do I need to execute the GRANT on the schema again after this view was created via the SYSTEM user?

Thanks,

Shounak

joachim_paulini3
Explorer
0 Kudos

Hi Thomas,

very helpful blog post! However, a questions which remains to me is about the security of the network protocol underneath the DB connection in DBAcockpit. Can it be securely used to connect to a HANA database in the cloud? Do you know which protocol/DB query technology is used?

Thanks a lot

Joachim

former_member182354
Contributor
0 Kudos

Hi Thomas,

                I read in one of your comments about the Kernal switch pilot which was in progress then. Is it live now?

               Can SQL be directed to secondary DB hana without any change in existing code?

Regards,

Raghav

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

The Kernel switch has been available to Max Attention customers for several years.

justin_molenaur2
Contributor
0 Kudos

As Thomas mentioned this is available and I helped a customer take this live. You can indeed redirect to the secondary DB without any code changes, only requires some configuration.

See this webinar for more information - "Speedup ABAP applications with SAP HANA Application Accelerator with little or no code changes"

http://www.hdespot.com/2015/09/16/hde-webinars/

Regards,

Justin

Former Member
0 Kudos

Hi,

Could you post an example setting the package size and fetch chunks of data until it ends ?

Former Member
0 Kudos

Hi Thomas,

My requirement is to use HANA as secondary database and insert multiple records in HANA table from ABAP program.

Am using below query to insert data in HANA database using Open SQL query in ABAP:

*******************************************************************************************

DATA(lv_statement) = | INSERT INTO "ABCD"."YTEST_HANA" VALUES('1234567895', '000')|.

TRY.

   DATA(lo_result_set) =

    cl_sql_connection=>get_connection( 'HA1'

    )->create_statement(

    tab_name_for_trace = CONV #( gc_view )

    )->execute_query( lv_statement ).

  CATCH cx_sql_exception INTO DATA(lo_ex).

ENDTRY.

********************************************************

This is working fine for direct value insertion, But when am trying to insert using variable as below it is throwing us a exception:

******************************************************************************************

DATA(lv_statement) = | INSERT INTO "ABCD""YTEST_HANA" VALUES(:LS_DATA-EBELN, :LS_DATA-EBELP)|.

TRY.

LOOP AT lt_data INTO ls_data.

   DATA(lo_result_set) =

    cl_sql_connection=>get_connection( 'HA1'

    )->create_statement(

    tab_name_for_trace = CONV #( gc_view )

    )->execute_query( lv_statement ).

    ENDLOOP.

  CATCH cx_sql_exception INTO DATA(lo_ex).

ENDTRY.

***************************************************************************************

Is there any way through coding to insert bulk data in HANA?

Looking forward to your valuable comments for Inserting data in HANA Table using workarea or structure.

Thanks,

Ajitesh

Former Member
0 Kudos

Hi Thomas,

Excellent blog.

Thanks a lot for writing this.

I am facing some issue .

I am able to create a table in sec. data base from  ABAP using native sql. Also I am able to fetch data.

But my methods to update data are not working (  example  Delete and insert).

Also I am not getting any error in ABAP code , sy-subrc is always 0. still i can  not see my updates in HANA DB.

What can be the reason ? DO we need any kind of commit statement or something?

Regards,

Meenu

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

I think you answered your own question at the end.  Yes an explicit commit is required.

Former Member
0 Kudos
Hi,

I installed the SAP AS 7.5 trial and now, and DB System was installed also.

To add the second connection (HANA Database) do I need to have this database (like Database in the SAP Cloud Platform Cockpit) or if I click on the Add button the SAP AS will create a secondary HANA database ?
raveeshsaurabh3
Active Participant
0 Kudos
Hi Thomas,

Wanted to understand if it is possible to access a DB table using ABAP which is created at HANA DB level, but not via SE11 in a S4H system?
thomas_jung
Developer Advocate
Developer Advocate
0 Kudos
Yes that's possible as that's exactly what this blog is describing.
raveeshsaurabh3
Active Participant
0 Kudos
Thanks Thomas for replying!  I was not talking about secondary connections. I was talking about a table created in underlying HDB of an S4 HANA system, although not created via SE11.

We have one of the scenarios where we have to create the custom table at HANA db level as it uses geospatial data types. But we want to access this table from S4H system using ABAP code(May be AMDP can be used) to get some of the details from this table.

Your comments are highly appreciated.

Regards

Raveesh
0 Kudos
Hi guys,

I have a question of how to access HANA native table stored in HANA secondary DB from local SAP BW (7.40 SP18 SP) system with ABAP (ADBC_QUERY or SELECT ... FROM... CONNECTION) if the HANA table is stored in a different/other schema than the default schema (schema with the name as DBCO - User name). The other schema is defined in DBCO - Conn.info according to SAP Note: 1983389 - DBCON entry for SAP HANA.

The HANA is configured in DBCO:


- User name: SAPHD1
- Conn.info: xxx:30015;SCHEMA=MKONECNY

The HANA native tables in schema SAPHD1 we can access from local SAP BW without problems.

All HANA native tables contain data, have Key field and have fields of table field types nvarchar or varchar, integer or decimal. Also, a local DDIC table in local SAP BW system is created with the same name and structure as HANA native table.

Does anybody have any experience with this situation?

Thank a lot.

Cheers,

Matus
0 Kudos
Hi thomas.jung,

I have a remote connection in DBCON (called "CONN1").

I am trying to INSERT * (all records) from SAP (DEFAULT connection) to a remote table (via DBCON connection "CONN1") with the same structure.

I have tried all kinds of syntax including:

EXEC SQL.

INSERT INTO CONN1.SCHEMA.TABLE_NAME

(SELECT * FROM TABLE_NAME)

ENDEXEC.

and I always get a short dump (SQL error).

My only success has been to insert all records from TABLE_NAME (in the DEFAULT SAP connection)  into an internal table (ITAB) and then Connect to CONN1 and then LOOP at the ITAB and INSERT records into the Remote table one by one. But this is VERY SLOW. We need to be able to do a INSERT with Sub-Select as I described above in two different schemas (CONN1 and DEFAULT).

Any advice you can provide will be greatly appreciated!

Thank you very much, Chris T.