【SAP Abap】X档案:SAP Native SQL 简介及实现方式(EXEC SQL、ADBC、AMDP)

news2024/11/14 14:56:20

SAP Native SQL 简介及实现方式(EXEC SQL、ADBC、AMDP)

  • 1、SAP Open SQL 与 Native SQL 的特点
  • 2、Native SQL 的实现方式
    • 方式一:Exec SQL
      • (1)获取单值
      • (2)获取多行
      • (3)游标应用
      • (4)错误捕获
      • (5)访问DBCO中配置的数据库链接
      • (6)执行DDL语句
      • (7)调用存储过程
      • (8)调用自定义函数
    • 方式二:ADBC
      • (9)ADBC示例
    • 方式三:AMDP
      • (10)编写SAP库存查询功能

1、SAP Open SQL 与 Native SQL 的特点

在 ABAP/4 编程语言中,提供了两种类型的 SQL。

第一种:Open SQL
在这里插入图片描述
(1)SAP 为 ABAP 定义的数据库无关的 SQL 标准, 为 SAP 支持的所有数据库系统提供了统一的语法和语义。
(2)ABAP中的Database Interface层负责将Open SQL在运行时由系统动态的转化成对应数据库使用的本地SQL。
(3)ABAPer在编写程序时不需要考虑 SAP 系统使用的数据库差异,操作的结果和任何错误消息都与正在使用的数据库系统无关。
(4)基于Open SQL开发的ABAP程序,可以在SAP系统中复用,而不用关心底层数据库的类型。
(5)Open SQL 语句只能访问在 ABAP 字典中创建的数据库表、视图,而不能操作那些直接通过数据库工具创建的表。
(6)Open SQL具有一些功能限制,即只有标准SQL的DML有对应的Open SQL,如:SELECT、INSERT, UPDATE, DELETE。

第二种:Native SQL
在这里插入图片描述
(1)每种关系型数据库都有其对应的 SQL,是数据库相关的。
(2)Native SQL绕过ABAP中的Database Interface层,不加转换的直接访问数据库层的Database Interface层。
(3)不同的 SAP 系统可能使用各种不同的数据库,使用Native SQL 的 ABAP 程序无法适应所有的 SAP 系统。
(4)Native SQL 通过设定的数据库链接,可以访问特定的数据库,可以访问不受 ABAP 字典管理的数据库对象,如表、视图、存储过程,以及外部的第三方数据库系统。
(5)Native SQL不会用到缓存,会直接发送给数据库,而不会经过ABAP数据访问层。除开DML,它一般用于DDL、DCL,可以用来维护数据库对象。
(6)可直接对数据库表进行修改删除等操作,有一定安全风险 。

说明及注意事项:
① SAP升级到S4之后,只支持SAP HANA数据库。理论上HANA数据库是向下兼容的,所以基于Hana的Native SQL的ABAP程序也具备复用性。
② Native SQL不会像Open SQL会默认过滤当前客户端号,所有语句都需要自己指定。
③ 本文仅做学习研究用,在SAP日常开发中,建议非必要不使用NativeSQL。

2、Native SQL 的实现方式

方式一:Exec SQL

语法:

EXEC SQL [PERFORMING <form_routine>].
  <native_sql_statements>
ENDEXEC.

SE11查看测试表SCARR的数据:
在这里插入图片描述

(1)获取单值

REPORT yz_demo1.
DATA: lv_count TYPE i.
EXEC SQL.
  select count(1) into :lv_count
  from saphanadb.scarr
  where mandt = :sy-MANDT ;
ENDEXEC.
WRITE:/ lv_count.

在这里插入图片描述

(2)获取多行

REPORT yz_demo2.
DATA: lv_carrid TYPE scarr-carrid,
      lv_carrname TYPE scarr-carrname.
EXEC SQL PERFORMING Write_data.
  select carrid, carrname into :lv_carrid,:lv_carrname
  from saphanadb.scarr
  where mandt = :sy-MANDT ;
ENDEXEC.

FORM Write_data.
  WRITE:/ lv_carrid,'',lv_carrname.
ENDFORM.

在这里插入图片描述

(3)游标应用

REPORT yz_demo3.
DATA: BEGIN OF gs_scarr,
      carrid TYPE scarr-carrid,
      carrname TYPE scarr-carrname,
  END OF gs_scarr.
EXEC SQL.
  OPEN cursor FOR
  select carrid, carrname
  from saphanadb.scarr
  where mandt = :sy-MANDT
ENDEXEC.
DO.
  CLEAR gs_scarr.
EXEC SQL.
    FETCH NEXT cursor INTO :gs_scarr
  ENDEXEC.
  IF sy-subrc <> 0.
    EXIT.
  ELSE.
    WRITE:/ gs_scarr-carrid,'',gs_scarr-carrname.
  ENDIF.
ENDDO.
EXEC SQL.
  CLOSE cursor
ENDEXEC.

在这里插入图片描述

(4)错误捕获

REPORT yz_demo4.
DATA lv_store_dbs TYPE dbcon-con_name.
DATA: lv_exc_ref TYPE REF TO cx_sy_native_sql_error,
      lv_error_text TYPE string.
TRY.
  EXEC SQL.
    CONNECT TO :lv_store_dbs
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
CATCH cx_sy_native_sql_error INTO lv_exc_ref.
  CLEAR: lv_error_text.
  lv_error_text  = lv_exc_ref->get_text( ).
  MESSAGE lv_error_text  TYPE 'I'.
ENDTRY.

在这里插入图片描述

(5)访问DBCO中配置的数据库链接

REPORT yz_demo5.

DATA conn TYPE dbcon-con_name.
cl_demo_input=>request( CHANGING field = conn ).
*SELECT SINGLE dbms
*FROM dbcon
*WHERE con_name = @conn AND dbms     = 'HDB'
*INTO @DATA(dbtype).
*
*IF sy-subrc <> 0.
*  RETURN.
*ENDIF.
TRY.
    EXEC SQL.
      CONNECT TO :conn
    ENDEXEC.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE cx_sy_native_sql_error
        EXPORTING
          textid = cx_sy_native_sql_error=>cx_sy_native_sql_error.
    ENDIF.
    EXEC SQL.
      OPEN dbcur FOR
        SELECT carrid
               FROM scarr
               WHERE mandt = :sy-mandt
    ENDEXEC.
    DATA carrid TYPE scarr-carrid.
    DO.
      EXEC SQL.
        FETCH NEXT dbcur INTO :carrid
      ENDEXEC.
      IF sy-subrc <> 0.
        EXIT.
      ELSE.
        cl_demo_output=>write(  |{ carrid }| ).
      ENDIF.
    ENDDO.
    EXEC SQL.
      CLOSE dbcur
    ENDEXEC.
    EXEC SQL.
      DISCONNECT :conn
    ENDEXEC.
  CATCH cx_sy_native_sql_error INTO DATA(exc).
    cl_demo_output=>write( exc->get_text( ) ).
ENDTRY.
cl_demo_output=>display( ).

在这里插入图片描述
在这里插入图片描述

(6)执行DDL语句

REPORT yz_demo6.
DATA: lv_count  TYPE i.
DATA: lv_exc_ref TYPE REF TO cx_sy_native_sql_error,
      lv_error_text TYPE string.
TRY.
  EXEC SQL.
    drop table ZStudent;
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
  EXEC SQL.
    create table ZStudent
    (
      ZNo     int,
      ZName   nvarchar(10),
      ZSex    nvarchar(1),
      ZAge    int,
      primary key (ZNo)
    );
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
  EXEC SQL.
    insert into ZStudent
    values( 1, '张三', '男', 18 );
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
  EXEC SQL.
      insert into saphanadb.ZStudent
    values( 2, '李四', '女', 19 );
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
  EXEC SQL.
    update ZStudent
    set zsex = '男', zage = 18
    where zname = '李四';
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
  EXEC SQL.
    select count(1) into :lv_count
    from ZStudent
    where zage = 18;
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
  EXEC SQL.
    commit;
  ENDEXEC.

CATCH cx_sy_native_sql_error INTO lv_exc_ref.
  CLEAR: lv_error_text.
  lv_error_text  = lv_exc_ref->get_text( ).
  MESSAGE lv_error_text  TYPE 'I'.
  EXEC SQL.
    rollback;
  ENDEXEC.
ENDTRY.
WRITE:/ '18岁的同学共有', lv_count, '位。' .

在这里插入图片描述

(7)调用存储过程

第1步:一般我们没有SAPHANADB的修改权限,也不建议在其中新建任何自定义对象,所以在SAPHANADB对应租户中新建用户NewUser,在新建用户名对应Schema下,定义如下存储过程:

create or replace procedure newuser.zp_scarr4
(
	IN I_CLIENT int default 300,	-- 传入参数:客户端号
	OUT O_CARRID varchar(10),		-- 传出参数:航空公司ID
	OUT O_CARRNAME varchar(50)		-- 传出参数:航空公司名称
)
as
begin
	select top 1 CARRID, CARRNAME 
	--注意事项:使用select into给参数或内部变量赋值,不需要 “:”
	into O_CARRID, O_CARRNAME
	from saphanadb.scarr 
	where mandt = :I_CLIENT;
end;
--在Hana studio中执行存储过程
call newuser.zp_scarr4(200,?,?);
--或者
call newuser.zp_scarr4(I_CLIENT=>200, O_CARRID => ?, O_CARRNAME => ?);

在这里插入图片描述
在这里插入图片描述
第2步:还需要设置SAPHANADB具有新建用户NewUser的执行权限:
在这里插入图片描述
第3步:开发ABAP程序,调用上述存储过程:

REPORT yz_demo7.
DATA: lv_carrid   TYPE scarr-carrid,
      lv_carrname TYPE scarr-carrname.
DATA: lv_exc_ref TYPE REF TO cx_sy_native_sql_error,
      lv_error_text TYPE string.
TRY.
  EXEC SQL.
    EXECUTE PROCEDURE newuser.zp_scarr4 ( IN :sy-mandt, OUT :lv_carrid, OUT :lv_carrname )
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
CATCH cx_sy_native_sql_error INTO lv_exc_ref.
  CLEAR: lv_error_text.
  lv_error_text  = lv_exc_ref->get_text( ).
  MESSAGE lv_error_text  TYPE 'I'.
ENDTRY.
WRITE: / lv_carrid, ' ', lv_carrname.

在这里插入图片描述

(8)调用自定义函数

第1步:在新建用户名NewUser对应Schema下,定义如下函数:

CREATE FUNCTION newuser.selfunc( mandt char(3), input CHAR(3) )
RETURNs output char(20) as
begin
	SELECT carrname
   	INTO output
   	FROM saphanadb.scarr
   	WHERE mandt  = mandt 
   	  AND carrid = input;
ENd;
--在Hana studio中调用函数
select newuser.selfunc( '200', 'AA') as carrname from dummy;

在这里插入图片描述
第2步:还需要设置SAPHANADB具有新建用户NewUser的查询权限:SELECT
第3步:开发ABAP程序,调用上述函数:

REPORT yz_demo8.
DATA: lv_carrid TYPE scarr-carrid VALUE 'AA',
      lv_carrname TYPE scarr-carrname.
DATA: lv_exc_ref TYPE REF TO cx_sy_native_sql_error,
      lv_error_text TYPE string.
TRY.
  EXEC SQL.
    select newuser.selfunc( :sy-mandt, :lv_carrid) into :lv_carrname from dummy;
  ENDEXEC.
  IF sy-subrc <> 0.
     RAISE EXCEPTION TYPE cx_sy_native_sql_error.
  ENDIF.
CATCH cx_sy_native_sql_error INTO lv_exc_ref.
  CLEAR: lv_error_text.
  lv_error_text  = lv_exc_ref->get_text( ).
  MESSAGE lv_error_text  TYPE 'I'.
ENDTRY.
WRITE: / lv_carrid, ' ', lv_carrname.

在这里插入图片描述

方式二:ADBC

ADBC(ABAP Database Connectivity,ABAP 数据库链接)的本质就是Native SQL,只是用类做了封装,更加符合面向对象的开发理念,相对开发更友好一些。

SAP为大家提供了 Native SQL接口API,该接口主要由四个类组成:
CL_SQL_STATEMENT - Execution of SQL Statements
CL_SQL_PREPARED_STATEMENT - Prepared SQL Statements
CL_SQL_CONNECTION - Administration of Database Connections
CX_SQL_EXCEPTION - Exception Class

SAP系统自带的DEMO程序:
在这里插入图片描述

(9)ADBC示例

REPORT yz_demo9.
TYPES:BEGIN OF result_t,
        ZNo   TYPE i,
        ZName TYPE string,
        ZSex  TYPE string,
        ZAge  TYPE i,
     END OF result_t.
DATA: 
*	  connection TYPE dbcon-con_name VALUE 'HAN',
      stmt_ref TYPE REF TO cl_sql_statement,
      cx_sql_exception TYPE REF TO cx_sql_exception,
      lv_text TYPE string,
      res_ref TYPE REF TO cl_sql_result_set,
      d_ref TYPE REF TO data,
      result_tab TYPE TABLE OF result_t,
      result_line TYPE result_t,
      row_cnt TYPE i,
      con_ref TYPE REF TO cl_sql_connection.

con_ref = cl_sql_connection=>get_connection(  ).  "connection,不传参则使用系统当前链接
stmt_ref = con_ref->create_statement( ).

TRY.
   stmt_ref->execute_ddl( 'create table saphanadb.ZStudent2( ZNo  int,ZName nvarchar(10),ZSex nvarchar(1),ZAge int, primary key (ZNo) );').
   stmt_ref->execute_update( 'insert into saphanadb.ZStudent2 values( 1, ''张三'', ''男'', 18 );' ).
   stmt_ref->execute_update( 'insert into saphanadb.ZStudent2 values( 2, ''李四'', ''女'', 19 );').
   stmt_ref->execute_update( 'update saphanadb.ZStudent2 set zsex = ''男'', zage = 18 where zname = ''李四'';' ).
   stmt_ref->execute_update( 'delete from saphanadb.ZStudent2 where zname = ''张三'';' ).
   res_ref = stmt_ref->execute_query( 'SELECT * FROM saphanadb.ZStudent2' ).
   GET REFERENCE OF result_tab INTO d_ref.
   res_ref->set_param_table( d_ref ).
   row_cnt = res_ref->next_package( ).
   stmt_ref->execute_ddl( 'DROP TABLE saphanadb.ZStudent2' ).
CATCH cx_sql_exception INTO cx_sql_exception.
   lv_text = cx_sql_exception->get_text( ).
   WRITE:/ 'Error:' , lv_text.
ENDTRY.

LOOP AT result_tab INTO result_line.
   WRITE:/ 'NO:' , result_line-ZNo, ' NAME:', result_line-ZName, ' SEX:', result_line-ZSex, ' AGE:', result_line-ZAge.
ENDLOOP.

在这里插入图片描述

方式三:AMDP

AMDP(ABAP-Managed Database Procedure),就是在ABAP层进行HANA数据库过程的实现和生命周期的管理。ABAP开发人员可以在 Eclipse 中使用 ADT 开发工具来创建、更改或删除 AMDP方法,AMDP类作为其管理容器,可以使用ABAP 传输机制来管理。
AMDP支持ABAP开发人员在ADT工具中编写HANA SQLScrip,即所谓的数据库存储过程。

(10)编写SAP库存查询功能

实现步骤1:定义一个AMDP全局类

class YCL_AMDP_HDB_INVENTORY definition
  public
  final
  create public .

PUBLIC SECTION.
    INTERFACES IF_AMDP_MARKER_HDB .     "集成系统AMDP接口

    TYPES:
    BEGIN OF TY_INVENTORY,
        MATNR TYPE MATNR_D,     "物料号
        WERKS TYPE WERKS_D,     "工厂
        LGORT TYPE LGORT_D,     "库存地点
        SOBKZ TYPE SOBKZ,       "特殊采购类型
        CHARG TYPE CHARG_D,     "批次
        LIFNR TYPE LIFNR,       "供应商
        KUNNR TYPE KUNNR,       "客户
        VBELN TYPE VBELN,       "销售凭证
        POSNR TYPE POSNR,       "销售凭证行项目
        FQTY  TYPE LABST,       "库存量
    END OF TY_INVENTORY .
    TYPES:
    TT_INVENTORY TYPE TABLE OF TY_INVENTORY WITH EMPTY KEY .

    "AMDP PROCEDURE实现,直接写SQLScript从HDB获取数据,也可以调用已封装好的数据库存储过程
    CLASS-METHODS GET_INVENTORY
    IMPORTING
      VALUE(P_CLNT) TYPE SY-MANDT
      VALUE(p_MATNR) TYPE MATNR
      VALUE(p_WERKS) TYPE WERKS_D
      VALUE(p_LGORT) TYPE LGORT_D
      VALUE(p_SOBKZ) TYPE SOBKZ
      VALUE(p_CHARG) TYPE CHARG_D
      VALUE(p_LIFNR) TYPE LIFNR
      VALUE(p_KUNNR) TYPE KUNNR
      VALUE(p_VBELN) TYPE VBELN
      VALUE(p_POSNR) TYPE POSNR
    EXPORTING
      VALUE(ET_INVENTORY) TYPE TT_INVENTORY.
      
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.

CLASS YCL_AMDP_HDB_INVENTORY IMPLEMENTATION.

  METHOD GET_INVENTORY
    BY DATABASE PROCEDURE FOR HDB
         LANGUAGE SQLSCRIPT
         OPTIONS READ-ONLY
         USING NSDM_V_MCHB NSDM_V_mkol NSDM_V_MSKA
            NSDM_V_MSLB NSDM_V_MCSD NSDM_V_MARD NSDM_V_MARC.

      ET_INVENTORY =
        SELECT
            MATNR, WERKS, LGORT, '' AS SOBKZ, CHARG,
            '' AS LIFNR, '' AS KUNNR,  '' AS VBELN,  '' AS POSNR,
            CLABS AS FQTY
        FROM NSDM_V_MCHB AS MCHB    --MCHB-批次库存
        WHERE CLABS <> 0
          AND MANDT = :P_CLNT
          AND ( MATNR = :p_MATNR OR :p_MATNR = '' )
          AND ( WERKS = :p_WERKS or :p_WERKS = '' )
          AND ( LGORT = :p_LGORT or :p_LGORT = '' )
          AND ( CHARG = :p_CHARG or :p_CHARG = '' )

        UNION
        SELECT
            MATNR, WERKS, LGORT, SOBKZ, CHARG,
            LIFNR, '' as KUNNR, '' as VBELN, '' as POSNR, SLABS as FQTY
        FROM NSDM_V_mkol as MKOL    --MKOL-寄售库存
        WHERE SLABS <> 0 and SOBKZ not in ( 'T', 'O' )
          AND MANDT = :P_CLNT
          AND ( MATNR = :p_MATNR or :p_MATNR = '' )
          AND ( WERKS = :p_WERKS or :p_WERKS = '' )
          AND ( LGORT = :p_LGORT or :p_LGORT = '' )
          AND ( SOBKZ = :p_SOBKZ or :p_SOBKZ = '' )
          AND ( CHARG = :p_CHARG or :p_CHARG = '' )
          AND ( LIFNR = :p_LIFNR or :p_LIFNR = '' )

        UNION
        SELECT
            MATNR, WERKS, LGORT, SOBKZ, CHARG,
            '' as LIFNR, '' as KUNNR, VBELN, POSNR, KALAB as FQTY
        from NSDM_V_MSKA as MSKA    --MSKA-销售订单库存
        where KALAB <> 0 and SOBKZ not in ( 'T', 'O' )
          AND MANDT = :P_CLNT
          AND ( MATNR = :p_MATNR or :p_MATNR = '' )
          AND ( WERKS = :p_WERKS or :p_WERKS = '' )
          AND ( LGORT = :p_LGORT or :p_LGORT = '' )
          AND ( SOBKZ = :p_SOBKZ or :p_SOBKZ = '' )
          AND ( CHARG = :p_CHARG or :p_CHARG = '' )
          AND ( VBELN = :p_VBELN or :p_VBELN = '' )
          AND ( POSNR = :p_POSNR or :p_POSNR = '000000' )

        UNION
        SELECT
            MATNR, WERKS, '' as LGORT, SOBKZ, CHARG,
            LIFNR, '' as KUNNR, '' as VBELN, '' as POSNR, LBLAB as FQTY
        from NSDM_V_MSLB as MSLB    --MSLB-供应商外包库存
        where LBLAB <> 0 and SOBKZ not in ( 'T', 'O' )
          AND MANDT = :P_CLNT
          AND ( MATNR = :p_MATNR or :p_MATNR = '' )
          AND ( WERKS = :p_WERKS or :p_WERKS = '' )
          AND ( SOBKZ = :p_SOBKZ or :p_SOBKZ = '' )
          AND ( CHARG = :p_CHARG or :p_CHARG = '' )
          AND ( LIFNR = :p_LIFNR or :p_LIFNR = '' )
          --*    and    LGORT in @LR_LGORT

        UNION
        SELECT
            MATNR, WERKS, LGORT, SOBKZ, CHARG,
            '' as LIFNR, KUNNR, '' as VBELN, '' as POSNR, SDLAB as FQTY
        from NSDM_V_MCSD as MCSD    --MCSD-客户库存
        where SDLAB <> 0 and SOBKZ not in ( 'T', 'O' )
          AND MANDT = :P_CLNT
          AND ( MATNR = :p_MATNR or :p_MATNR = '' )
          AND ( WERKS = :p_WERKS or :p_WERKS = '' )
          AND ( LGORT = :p_LGORT or :p_LGORT = '' )
          AND ( SOBKZ = :p_SOBKZ or :p_SOBKZ = '' )
          AND ( CHARG = :p_CHARG or :p_CHARG = '' )
          AND ( KUNNR = :p_KUNNR or :p_KUNNR = '' )

        UNION
        SELECT
            MARD.MATNR, MARD.WERKS, MARD.LGORT, '' as SOBKZ, '' as CHARG,
            '' as LIFNR, '' as KUNNR, '' as VBELN, '' as POSNR, MARD.LABST AS FQTY
        FROM NSDM_V_MARD AS MARD    --MARD-仓库库存
        INNER JOIN NSDM_V_MARC as MARC ON MARD.MATNR = MARC.MATNR AND MARC.WERKS = MARD.WERKS AND MARD.MANDT = MARC.MANDT
        WHERE MARD.LABST <> 0
          AND MARD.MANDT = :P_CLNT
          AND MARC.XCHAR =  ''
          AND ( MARD.MATNR = :p_MATNR or :p_MATNR = '' )
          AND ( MARD.WERKS = :p_WERKS or :p_WERKS = '' )
          AND ( MARD.LGORT = :p_LGORT or :p_LGORT = '' )
          ;
  ENDMETHOD.
  
ENDCLASS.

实现步骤2:定义一个ABAP程序来调用AMDP全局类

*&---------------------------------------------------------------------*
*& Report YZ_AMDP_DEMO
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT yz_amdp_demo.

TYPES:
    BEGIN OF ty_inventory,
        matnr TYPE matnr_d,     "物料号
        werks TYPE werks_d,     "工厂
        lgort TYPE lgort_d,     "库存地点
        sobkz TYPE sobkz,       "特殊采购类型
        charg TYPE charg_d,     "批次
        lifnr TYPE lifnr,       "供应商
        kunnr TYPE kunnr,       "客户
        vbeln TYPE vbeln,       "销售凭证
        posnr TYPE posnr,       "销售凭证行项目
        fqty  TYPE labst,       "库存量
    END OF ty_inventory .
TYPES:
    tt_inventory TYPE TABLE OF ty_inventory WITH EMPTY KEY .

DATA: gt_inventory TYPE tt_inventory.

DATA: iv_matnr TYPE  matnr,
      iv_werks TYPE  werks_d,
      iv_lgort TYPE  lgort_d,
      iv_sobkz TYPE  sobkz,
      iv_charg TYPE  charg_d,
      iv_lifnr TYPE  lifnr,
      iv_kunnr TYPE  kunnr,
      iv_vbeln TYPE  vbeln,
      iv_posnr TYPE  posnr.

DATA: gt_fieldcat   TYPE lvc_t_fcat WITH HEADER LINE.         " 字段目录

START-OF-SELECTION.

  IF cl_abap_dbfeatures=>use_features(
            EXPORTING
              requested_features = VALUE #( ( cl_abap_dbfeatures=>call_amdp_method )
                                                    ( cl_abap_dbfeatures=>amdp_table_function ) ) ).

    TRY ."异常捕捉
      ycl_amdp_hdb_inventory=>get_inventory(
        EXPORTING
          p_clnt       =  sy-mandt
          p_matnr      =  iv_matnr
          p_werks      =  iv_werks
          p_lgort      =  iv_lgort
          p_sobkz      =  iv_sobkz
          p_charg      =  iv_charg
          p_lifnr      =  iv_lifnr
          p_kunnr      =  iv_kunnr
          p_vbeln      =  iv_vbeln
          p_posnr      =  iv_posnr
        IMPORTING
          et_inventory = gt_inventory ).

      CATCH cx_ai_system_fault INTO DATA(zcl_cx_ai_system_fault).
*        EV_STATUS = 'E'.
*        EV_MESSAGE =  ZCL_CX_AI_SYSTEM_FAULT->GET_TEXT( ).
        EXIT.
      CATCH cx_ai_application_fault INTO DATA(zcl_cx_ai_application_fault).
*        EV_STATUS = 'E'.
*        EV_MESSAGE = ZCL_CX_AI_APPLICATION_FAULT->GET_TEXT( ).
        EXIT.
    ENDTRY.

      "cl_demo_output=>display( GT_INVENTORY ).   " 报错,改用ALV显示
      PERFORM frm_alv_show.
  ELSE.
    cl_demo_output=>display( '警告!当前系统不支持AMDP.' ).
  ENDIF.


FORM frm_alv_show .
  DATA: w_layout   TYPE lvc_s_layo.
  CLEAR w_layout.
  w_layout-zebra = 'X'.
  w_layout-col_opt = 'X'.

  PERFORM frm_build_fieldcat.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program          = sy-repid
      is_layout_lvc                = w_layout
      it_fieldcat_lvc              = gt_fieldcat[]
*      i_default                = 'X'
*      i_save                   = 'A'
    TABLES
      t_outtab                 = gt_inventory
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.                    " FRM_ALV_SHOW

FORM frm_build_fieldcat.
  DEFINE mac_field.
    gt_fieldcat-fieldname = &1. " 内表字段名
    gt_fieldcat-reptext = &2.
    APPEND gt_fieldcat.
  end-OF-DEFINITION.

   mac_field:  'MATNR' '物料号',
               'WERKS' '工厂',
               'LGORT' '库存地点',
               'SOBKZ' '特殊采购类型',
               'CHARG' '批次',
               'LIFNR' '供应商',
               'KUNNR' '客户',
               'VBELN' '销售凭证',
               'POSNR' '销售凭证行项目',
               'FQTY' '库存量'.

 ENDFORM.

更多详细介绍,请参考待发布的专题文章《SAP AMDP实现方法简介》。

原创文章,转载请注明来源-X档案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/172204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TCP协议的长连接和短连接详解

一 前言TCP在真正开始进行数据传输之前&#xff0c;Server 和 Client 之间必须建立一个连接。当数据传输完成后&#xff0c;双方不再需要这个连接时&#xff0c;就可以释放这个连接。TCP连接的建立是通过三次握手&#xff0c;而连接的释放是通过四次挥手。所以说&#xff0c;每…

【SpringCloud】Eureka的基本原理与使用

【SpringCloud】Eureka的基本原理与使用 一、Eureka-提供者与消费者 【问】如果服务A调用了服务B&#xff0c;而服务B又调用了服务C&#xff0c;服务B的角色是什么&#xff1f; 二、Eureka的结构和作用 什么是Eureka&#xff1f; Eureka 解决服务调用的问题 order-servic…

博物馆3d数字化全景展示设计方案

作为近几年新兴的营销方式&#xff0c;交互式营销能够让消费者对产品从主动感兴趣到互动体验&#xff0c;甚至自主自发传播&#xff0c;达到“在销售中传播&#xff0c;在传播中销售”的目的。进入数字体验经济时代&#xff0c;当3d数字化展示技术遇上传统行业&#xff0c;3d数…

Redis原理篇(三)通信协议

一、RESP协议 1、定义 Redis是一个cs架构的软件&#xff0c;通信一般分两步&#xff1a; 客户端client向服务端server发送一条命令服务端解析并执行命令&#xff0c;返回响应结果给客户端 因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范&#xff0c;这个规…

HashMap源码学习:JDK1.8版本源码解析

文章导航 HashMap源码学习&#xff1a;红黑树原理详解 HashMap源码学习&#xff1a;JDK1.8版本源码解析 目录文章导航前言正文HashMap重要属性HashMap构造方法HashMap扩容方法HashMap链表迁移HashMap红黑树迁移HashMap链表转红黑树HashMap红黑树转链表HashMap添加数据HashMap移…

让你彻底明白Java SPI与SpringBoot自动配置,内附实例代码演示

一、Java SPI的概念和术语 SPI&#xff1a;全称是Service Provider Interface&#xff1a;是一种基于ClassLoader来发现并加载服务的机制 SPI由三个组件构成&#xff1a;Service、Service Provider、ServiceLoader Service&#xff1a;是一个公开的接口或抽象类&#xff0c;定…

数说菊风2022

春风传捷报&#xff0c; 梅韵贺新年&#xff01; 2022&#xff0c;已悄然划过&#xff0c; 就让我们用数字说话&#xff0c; 述说这年的精彩&#xff01; 树十大标杆案例 国际运营商战略合作——Telkomsel 携手印尼运营商Telkomsel在RCS融合通信和RTC实时音视频领域形成合…

golang入门笔记——kitex

WSL的安装 由于Kitex并不支持Linux&#xff0c;所以需要首先安装WSL2 WSL一句话来说就是微软出的一个虚拟机工具 Win11下安装WSL2的步骤为&#xff1a; 1.“开始菜单”搜索功能&#xff0c;打开“启动或关闭Window功能” 2.勾选以下功能 1.适用于Linux的Window子系统 2.虚…

qsort函数

目录1.什么是qsort函数2.实现一个qsort函数3.用qsort函数排序一个结构体4.模仿qsort的功能实现一个通用的冒泡排序1.什么是qsort函数 我们以前学习过的一些排序算法&#xff0c;如冒泡、希尔、快排等等&#xff0c;它们速度有快有满&#xff0c;但是这些排序都只能排序一种类型…

iOS 内存泄漏检测 Instruments Leaks

Xcode 中 按住 command I 或者菜单栏 Product – Profile 2. 双击 Leaks 或者按 choose&#xff0c;打开 Leaks 面板 3. 在显示的 Leaks 面板中&#xff0c;点击左上角红色点&#xff0c;即可运行内存检测。 4. 在运行过程中如果发现Leak Checks&#xff08;如图&#xff09;…

【C进阶】C进阶练习编程题

⭐博客主页&#xff1a;️CS semi主页 ⭐欢迎关注&#xff1a;点赞收藏留言 ⭐系列专栏&#xff1a;C语言进阶 ⭐代码仓库&#xff1a;C Advanced 家人们更新不易&#xff0c;你们的点赞和关注对我而言十分重要&#xff0c;友友们麻烦多多点赞&#xff0b;关注&#xff0c;你们…

关闭“此版本的Windows不再支持Microsoft Edge”提示

在Win7中&#xff0c;安装Microsoft Edge&#xff0c;升级到“109.0.1518.55 (正式版本)”后&#xff0c;打开Edge会弹出提示&#xff1a; 此版本的 Windows 不再支持 Microsoft Edge。升级到 Windows 10 或更高版本&#xff0c;以从 Microsoft Edge 获取常规功能和安全更新。 …

ESPNet: 自动驾驶领域轻量级分割模型

论文标题&#xff1a;ESPNet: Efficient Spatial Pyramid of Dilated Convolutions for Semantic Segmentation 论文地址&#xff1a;https://arxiv.org/pdf/1803.06815v2.pdf 开源地址&#xff1a; https://github.com/sacmehta/ESPNet 论文思想 ESPNet是用于语义分割的轻量…

一文弄懂Linux虚拟机网络配置

文章目录计算机网路基础网络连接模式Bridged&#xff08;桥接模式&#xff09;NAT&#xff08;地址转换模式&#xff09;Host-Only&#xff08;仅主机模式&#xff09;Linux常用网络相关命令ifconfig&#xff1a;配置网络接口ping&#xff1a;测试主机之间网络连通性修改ip地址…

Threejs 导入动态模型 - 兔子岛

Threejs 动画模型GLTF加载器&#xff08;GLTFLoader&#xff09; glTF&#xff08;gl传输格式&#xff09;是一种开放格式的规范 &#xff08;open format specification&#xff09;&#xff0c; 用于更高效地传输、加载3D内容。该类文件以JSON&#xff08;.gltf&#xff09;…

产品心理学:福格行为模型详解与应用

​Fogg说人的行为由动机&#xff0c;能力和触发条件这三要素组成&#xff0c;这三个同时都满足时行为才会发生。用一个等式来简化就是&#xff1a; BMAT 其中B是Behavior行为&#xff0c;M是Motivation 动机&#xff0c;A是Ability能力&#xff0c;T是Triggers触发。 行为的发…

“华为杯”研究生数学建模竞赛2004年-【华为杯】B题:实用下料的数学模型(附优秀论文)

赛题描述 “下料问题(cutting stock problem)”是把相同形状的一些原材料分割加工成若干个不同规格大小的零件的问题,此类问题在工程技术和工业生产中有着重要和广泛的应用. 这里的“实用下料问题”则是在某企业的实际条件限制下的单一材料的下料问题。 一个好的下料方案首先…

JavaEE4-Spring使用

目录 1.存储Bean对象到Spring容器中 1.1.创建Bean 1.2.将Bean注册到Spring容器中 1.2.1.第一次存储Bean&#xff08;可选&#xff0c;如果是第二次及以后&#xff0c;此步骤忽略&#xff09; 1.2.2.添加Bean标签 2.从Spring容器中获取并使用Bean对象 2.1.创建Spring上下…

ADC架构_Flash

ADC架构_Flash 比较器做1位ADC Vin > Vref Vout High&#xff08;1&#xff09; Vin < Vref Vout Low&#xff08;0&#xff09; 比较器是组建集成ADC的内部基本而又关键的模块&#xff1b;在比较器应用在ADC中一般要求很高的分辨率&#xff0c;也就是很小的差分输…

Spring Security 认证研究

2 Spring Security 认证研究 2.1 Spring Security介绍 认证功能几乎是每个项目都要具备的功能&#xff0c;并且它与业务无关&#xff0c;市面上有很多认证框架&#xff0c;如&#xff1a;Apache Shiro、CAS、Spring Security等。由于本项目基于Spring Cloud技术构建&#xff…