【SAP Abap】X档案:SAP ABAP 中 AMDP 简介及实现方法

news2024/9/29 5:30:47

SAP ABAP 中 AMDP 简介及实现方法

  • 0、前言
  • 1、AMDP 简介
    • 1.1 代码下沉(Code Pushdown)
    • 1.2 AMDP 是托管数据库过程的容器
    • 1.3 AMDP 的优缺点
    • 1.4 几种数据库访问方式的区别
    • 1.5 几种数据库访问方式的选用
    • 1.6 使用的开发工具
  • 2、实现方法
    • 2.1 AMDP PROCEDURE(存储过程)实现
    • 2.2 AMDP FUNCTION(函数)实现
  • 3、实例DEMO
  • 附、AMDP异常

0、前言

因为我以往的开发经历,习惯了在数据库端开发存储过程,封装业务逻辑,然后给应用层(.Net 或者 Java)调用;又因为我基于SAP HANA一体机做过数据仓库开发,比较熟悉HANA SQL开发,尤其是传统方式的视图、函数、存储过程开发;再加上对比了Hana数据库与其他传统关系型数据库内存计算性能之强大,所以在对 ABAP 程序做性能优化过程中,对于一些比较复杂的数据计算逻辑或大数据量计算的需求,就想着有没有方法让 ABAP 调用 Hana 数据库端存储过程来实现,以此来发挥 Hana 内存计算优势。这个思路,也正好与SAP Code Pushdown 思路契合一致。SAP正是由于更改了策略,调整其应用系统使用自家的SAP HANA数据库之后,统一了底层数据库,也就使得这个思路具备了实现的条件。

1、AMDP 简介

1.1 代码下沉(Code Pushdown)

随着 SAP HANA 的不断发展,促使 ABAP AS 与 SAP HANA 的结合越来越紧密,如今SAP S4 产品只支持 SAP HANA 数据库。
在这里插入图片描述
在如此背景下,ABAP 7.40 SP05 的发布,SAP ABAP 引入了一种新的应用开发范式,即所谓的代码下沉(Code Pushdown)。

传统的 ABAP 应用开发方式,即下图左边的 Data to Code,数据库仅仅作为数据的静态存储仓库,ABAP 应用开发人员通过 Open SQL 等方式将数据从数据库层读取到ABAP 应用层,再在 ABAP 应用层进行数据处理。
在这里插入图片描述
Code Pushdown 意味着一种编程理念的转变,即上图右边所示,将密集的数据计算从 ABAP 应用层下推到 HANA 数据库层,然后再将少量的计算结果传输到 ABAP 应用层加以展示,从而充分发挥 HANA 数据库高性能的数据处理能力。

而要实现 Code Pushdown ,SAP 必须提供一种技术,能够允许 ABAP 开发人员在应用层直接编写HANA 数据库层应用逻辑。这些应用逻辑可以实现在所谓的数据库过程(Database Procedure)里,实现语言为SAP HANA SQL Script。
在这里插入图片描述

1.2 AMDP 是托管数据库过程的容器

AMDP 托管数据库过程(ABAP-Managed Database Procedure,以下简称 AMDP ),即在 ABAP 层进行 HANA 数据库过程的实现和生命周期(Lifecycle)的管理。
在这里插入图片描述
开发人员使用Eclipse的ADT(ABAP Development Tool)工具,通过在 ABAP 层开发 AMPD 类, 使用 HANA SQL Script 编写具体逻辑,作为 AMDP 类的 AMDP 方法的实现,以此达到在 ABAP 层直接消费 HANA 数据库层原生功能的目的。在应用层即 ABAP 程序中管理数据计算逻辑和建模,激活后会在 HANA 中创建相应的数据库对象。这种特殊的 ABAP 类方法,作为 HANA SQLScript 的承载容器,使得 AMDP 同其他普通的 ABAP 开发对象一样,采取统一的 ABAP传输管理,生命周期管理,代码缺陷修复和升级管理方式。

使用 AMDP,可以将 ABAP Application 编写的代码通过 HANA 的新特性(代码下推技术),将逻辑在数据库层执行。除了 AMDP 之外,数据库过程代理是另一种 HANA 数据库过程的实现方式。这种方式首先在 HANA repository 里创建一个 HANA 原生的数据库过程,再到 ABAP 层创建一个代理指向前者,在 ABAP 应用里通过使用该代理对象,消费 HANA 仓库里的原生数据库过程。同 AMDP 相比,这种方式需要在 HANA 层进行原生开发,而 AMDP 则是在应用层提供了简单的调用SQL Script等数据库语言的方式。因此在实际的开发场景中,SAP更推荐使用AMDP。

1.3 AMDP 的优缺点

优点:

  • 可以充分发挥 Hana内存计算优势;
  • 能对 SQL Script 的静态代码检查(相比 NativeSQL);
  • 具备语法高亮(支持pretty printer格式优化器);
  • 在AMDP方法内不光能访问ABAP字典的视图和表,还能访问其它AMDP方法;
  • 可以像普通的ABAP方法一样调用(不包括AMDP function);
  • 可以进行传输管理(相比数据库传统开发模式);
  • 可以使用ST22进行运行时错误的详细分析。

缺点:

  • AMDP 还不能在 Eclipse、HANA Studio 上进行 Debug 操作;
  • 不能使用被代理表,如mseg表,但可以使用它的代理对象 NSDM_V_MSEG,或者直接访问 Hana 新表 MATDOC表;
  • 数据类型必须是表或者标准类型(INT CHAR …);
  • 对于传入的 Select-option,必须先在 ABAP 中用方法 cl_shdb_seltab=>combine_seltabs 处理后在传入 AMDP ;然后在AMDP中用 APPLY_FILTER;
  • AMDP 不能自动处理 Client 信息,使用时必须传入 SY-MANDT;否则取出来的数据是所有 Client 的全部数据。

1.4 几种数据库访问方式的区别

访问方式依赖ABAP DDIC,支持引用列表托管数据库连接禁用DDL自动Client、应用缓存
Open SQL
AMDP受限
ABAP Managed Native SQL受限
Non-ABAP-Managed Native SQL

1.5 几种数据库访问方式的选用

按SAP的官方建议,在可以使用Open SQL实现需要的功能或优化目标的时候,不建议使用AMDP。而在需要使用Open SQL不支持的特性,或者是大量处理流和分析导致了数据库和应用服务器之间有重复的大量数据传输的情况下,则应当使用AMDP。
在这里插入图片描述

几种方式的推荐使用顺序:

  • 优先使用OpenSQL 和 CDS,因为它简化了许多方面,例如客户端处理,并使编程变得简单,例如因为它可以巧妙地读取类型结构和表。因为OpenSQL能够访问CDS,所以推荐使用 CDS View来实现 Code Pushdown。
  • 如果数据计算复杂或者数据量特别大,为减轻应用层计算压力、降低数据库和应用层之间大量数据传输的网络负载,则可以考虑使用 Code Pushdown,将代码下沉到 Hana 数据库端实现,即采用 AMDP 托管数据库过程的方法。
  • 如果以上两种方法都无法达到目标,例如因为需要连接到另一个数据库或需要使用具有不同授权的辅助数据库连接,那么可以使用 ADBC ,不建议使用 Native SQL。

1.6 使用的开发工具

AMDP 在 SAP NetWeaver AS ABAP 7.40 SP05 版本中被引入。只有基于 Eclipse 的开发工具(即ADT,版本要不低于2.19)才支持 AMDP 类的编辑,SAP GUI 上面的 SE80 是不提供编辑功能的,只能用来阅读代码。
在这里插入图片描述

2、实现方法

AMDP类就是普通的类,只是实现了 IF_AMDP_MARKER_<DB_TYPE> 接口。如果是 HANA 数据库,那么就是实现接口 IF_AMDP_MARKER_HDB。虽然原则上 AMDP 是为了支持各种数据库的存储过程而存在的,但到目前(ABAP 7.52)为止,AMDP 只支持 SAP HANA 数据库。

AMDP 方法有两种实现,一种是 AMDP procedure 实现;另一种是 AMDP function 实现。

2.1 AMDP PROCEDURE(存储过程)实现

  • 这种方法,需要在实现 Method 时,使用附加项 BY DATABASE PROCEDURE。
  • 这种方法,它将AMDP方法实现为一个 Hana 数据库端的 procedure。
  • 这种方法,可以定义为公共的静态方法或者实例方法。
  • 这种方法和普通的 ABAP 对象方法在使用方式上没区别,ABAP 程序可以直接调用。

语法结构如下:

CLASS <my_amdp_class> DEFINITION.
  PUBLIC SECTION.
* 指定的Marker接口
  INTERFACES IF_AMDP_MARKER_<DB_TYPE>.
  [CLASS-]METHODS <my_amdp_method>
    [IMPORTING list]
    [EXPORTING list].
ENDCLASS.

CLASS <my_amdp_class> IMPLEMENTATION.
* AMDP 存储过程方法 
  METHOD <my_amdp_method> 
    BY DATABASE PROCEDURE 
    FOR <db_type>
    LANGUAGE <db_language>
    OPTIONS <db_options>  
    USING   <db_entity>.
    --使用数据库语言实现存储过程
  ENDMETHOD.
ENDCLASS.

说明:

  • BY DATABASE PROCEDURE: 实现一个数据库过程。
  • FOR HDB: 指定数据库类型为 HANA database。
  • LANGUAGE SQLSCRIPT: 指定用于实现AMDP的数据库特定语言为 SQLSCRIPT。
  • OPTION READ-ONLY: 设置只能在存储过程中读取数据库。
  • USING <table_name/view_name/amdp_func_method_name>: 设置使用的数据库表、视图或者是已定义的AMDP FUNCTION实现。

2.2 AMDP FUNCTION(函数)实现

  • 这种方法,需要在实现 Method 时,使用附加项 BY DATABASE FUNCTION。
  • 这种方法,它将 AMDP 方法实现为一个 Hana 数据库端的 function,可以是scalar function(值函数),也可以是table function(表函数)。
  • 这种方法不能被 ABAP 程序直接调用,只能被 AMDP PROCEDURE 方法使用。
  • 这种方法,实现 Table 时还有两种细分的实现方式,一种是 TABLE FUNCTION,可以定义为私有的静态方法或实例方法,另一种是 TABLE FUNCTION CDS,必须定义为公共的静态方法。

补充说明:

  • scalar function 是只读的用户定义的值函数,可以接收多个输入参数,接收单一的标量返回值。在 SQL Scitpt 中可以放在字段相同的位置使用。
  • table function 是只读的用户定义的表函数,可以接收多个输入参数,接收单一的表返回值。在 SQL Scitpt 中可以放在与数据库表或者视图相同的位置使用。
  • table function cds,可以简单理解为对 table function 名称(类名称=>方法名称)的一个形式转换,以 view 视图的方式来呈现。

语法结构如下:

CLASS <my_amdp_class> DEFINITION.
  PUBLIC SECTION.
* 指定的Marker接口
  INTERFACES IF_AMDP_MARKER_<DB_TYPE>.
  CLASS-METHODS <my_amdp_method_for_cds> FOR TABLE FUNCTION <my_cds_name>.
  PRIVATE SECTION.
  [CLASS-]METHODS <my_amdp_method>
    [IMPORTING list]
    [RETURNING single_value_or_table].
ENDCLASS.

CLASS <my_amdp_class> IMPLEMENTATION.
* AMDP 函数方法 
  METHOD <my_amdp_method> 
    BY DATABASE FUNCTION
    FOR <db_type>
    LANGUAGE <db_language>
    OPTIONS <db_options>  
    USING   <db_entity>.
	--使用数据库语言实现函数
	--值函数不需要return,表函数必须要return
    [RETURN select_from_table.]	
  ENDMETHOD.

  METHOD <my_amdp_method_for_cds> 
    BY DATABASE FUNCTION
    FOR <db_type>
    LANGUAGE <db_language>
    OPTIONS <db_options>  
    USING   <db_entity>.
	--使用数据库语言实现函数
    RETURN select_from_table.
  ENDMETHOD.
ENDCLASS.

说明:

  • BY DATABASE FUNCTION: 实现一个数据库函数。
  • FOR HDB: 指定数据库类型为 HANA database。
  • LANGUAGE SQLSCRIPT: 指定用于实现AMDP的数据库特定语言为 SQLSCRIPT。
  • OPTION READ-ONLY: 设置只能在存储过程中读取数据库。
  • USING <table_name / view_name / amdp_class_name=>method_name >: 设置使用的数据库表、视图或者是已定义的 AMDP FUNCTION 实现。

3、实例DEMO

步骤1:在ADT中,定义一个AMDP类,继承接口:IF_AMDP_MARKER_HDB

CLASS ycl_amdp_hdb_demo DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

PUBLIC SECTION.
  INTERFACES IF_AMDP_MARKER_HDB .     "继承系统AMDP接口"

    TYPES:
        BEGIN OF ty_scarr,
            mandt     TYPE S_MANDT,
            carrid    TYPE s_carr_id,
            carrname  TYPE s_carrname,
            url       TYPE s_carrurl,
        END OF ty_scarr .
    TYPES:
        tt_scarr TYPE TABLE OF ty_scarr WITH EMPTY KEY .

  " 常规方法:Open SQL "
  CLASS-METHODS GET_SCARR_BY_OPENSQL
    IMPORTING
      VALUE(p_clnt)     TYPE s_mandt
      VALUE(p_carrid)   TYPE s_carr_id
      VALUE(p_carrname) TYPE s_carrname
      VALUE(p_url)      TYPE s_carrurl
    EXPORTING
      VALUE(et_scarr)   TYPE tt_scarr.


  "AMDP方式1: AMDP PROCEDURE实现,直接写SQLScript从HDB获取数据 "
  " 也可直接调用已创建的数据库对象,如存储过程、视图、函数等 "
  " 该方法可以直接被ABAP程序调用,必须设置为PUBLIC "
    CLASS-METHODS GET_SCARR
    IMPORTING
      VALUE(p_clnt)     TYPE s_mandt
*      VALUE(p_carrid)   TYPE s_carr_id
*      VALUE(p_carrname) TYPE s_carrname
*      VALUE(p_url)      TYPE s_carrurl
    EXPORTING
      VALUE(et_scarr) TYPE tt_scarr.

  "AMDP方式2-1-1: AMDP function实现,直接写SQLScript从HDB获取数据 "
  " 该方法不能直接被ABAP程序调用,只能在AMDP PROCEDURE实现中调用,建议可设置为 PRIVATE "
  CLASS-METHODS GET_SCARR_FUNC
    IMPORTING
      VALUE(p_clnt)     TYPE s_mandt
*      VALUE(p_carrid)   TYPE s_carr_id
*      VALUE(p_carrname) TYPE s_carrname
*      VALUE(p_url)      TYPE s_carrurl
    RETURNING
      VALUE(et_scarr)   TYPE tt_scarr.

	"AMDP方式2-1-2: AMDP procedure实现,调用上述的 AMDP function实现 "
    CLASS-METHODS GET_SCARR_BY_FUNC
    IMPORTING
      VALUE(p_clnt)     TYPE s_mandt
*      VALUE(p_carrid)   TYPE s_carr_id
*      VALUE(p_carrname) TYPE s_carrname
*      VALUE(p_url)      TYPE s_carrurl
    EXPORTING
      VALUE(et_scarr)   TYPE tt_scarr.
  
  "AMDP方式2-2-1: AMDP procedure实现,为 TABLE FUNCTION CDS编写具体实现逻辑 "
  " 该方法无法直接被ABAP程序调用,但是对应的CDS可以被ABAP调用。 "
  " 此处对应的CDS名为:YCDS_INVENTORY,需要另外单独定义 "
  " 定义为 TABLE FUNCTION CDS 时,方法必须为 PUBLIC CLASS-METHODS "
  CLASS-METHODS GET_SCARR_FOR_CDS FOR TABLE FUNCTION YCDS_ADMP_DEMO_SCARR.

  "AMDP方式2-1-2: AMDP procedure实现,调用上面 AMDP function 实现的CDS "
  CLASS-METHODS GET_SCARR_BY_CDS
    IMPORTING
      VALUE(p_clnt)     TYPE s_mandt
*      VALUE(p_carrid)   TYPE s_carr_id
*      VALUE(p_carrname) TYPE s_carrname
*      VALUE(p_url)      TYPE s_carrurl
    EXPORTING
      VALUE(et_scarr) TYPE tt_scarr.

PROTECTED SECTION.
PRIVATE SECTION.

ENDCLASS.

CLASS ycl_amdp_hdb_demo IMPLEMENTATION.

  METHOD GET_SCARR_BY_OPENSQL.
    select mandt, carrid, carrname, url
    from scarr
    where ( carrid = @p_carrid or @p_carrid = '' )
       or ( carrname = @p_carrname or @p_carrname = '' )
       or ( url = @p_url or @p_url = '' )
    into CORRESPONDING FIELDS OF TABLE @et_scarr.
  ENDMETHOD.

  METHOD GET_SCARR
    BY DATABASE PROCEDURE FOR HDB
         LANGUAGE SQLSCRIPT
         OPTIONS READ-ONLY
         USING SCARR.
      ET_SCARR =
        SELECT
            MANDT, CARRID, CARRNAME, URL
        FROM SCARR
        WHERE MANDT = :p_clnt;
  endmethod.

  method GET_SCARR_FUNC
    BY DATABASE FUNCTION FOR HDB
         LANGUAGE SQLSCRIPT
         OPTIONS READ-ONLY
         USING SCARR.
    RETURN
        SELECT
            MANDT, CARRID, CARRNAME, URL
        FROM SCARR
        WHERE MANDT = :p_clnt;
  ENDMETHOD.

  METHOD GET_SCARR_BY_FUNC
    BY DATABASE PROCEDURE FOR HDB
         LANGUAGE SQLSCRIPT
         OPTIONS READ-ONLY
         using ycl_amdp_hdb_demo=>GET_SCARR_FUNC.
     ET_SCARR =
       select *
       from "YCL_AMDP_HDB_DEMO=>GET_SCARR_FUNC"
       (p_clnt => :p_clnt);
  ENDMETHOD.

    METHOD GET_SCARR_FOR_CDS
         BY DATABASE FUNCTION FOR HDB
         LANGUAGE SQLSCRIPT
         OPTIONS READ-ONLY
         USING SCARR.
    RETURN
        SELECT
            MANDT, CARRID, CARRNAME, URL
        FROM SCARR
        WHERE MANDT = :p_clnt;
  ENDMETHOD.

  METHOD GET_SCARR_BY_CDS
    BY DATABASE PROCEDURE FOR HDB
         LANGUAGE SQLSCRIPT
         OPTIONS READ-ONLY
         using YCDS_ADMP_DEMO_SCARR.
     ET_SCARR =
        select MANDT, CARRID, CARRNAME, URL
        from YCDS_ADMP_DEMO_SCARR( P_CLNT => :P_CLNT );
  ENDMETHOD.

ENDCLASS.

步骤2:在ADT中,定义 TABLE FUNCTION CDS

@EndUserText.label: 'ADMP_DEMO_SCARR'
define table function YCDS_ADMP_DEMO_SCARR
with parameters 
    @Environment.systemField: #CLIENT
    p_clnt  : abap.clnt
returns {
  mandt     : abap.clnt;
  carrid    : s_carr_id;
  carrname  : s_carrname;
  url       : s_carrurl;
}
implemented by method ycl_amdp_hdb_demo=>get_scarr_for_cds;

步骤3:在SAP中,开发ABAP程序,调用AMDP类

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

TYPES:
    BEGIN OF ty_scarr,
        mandt     TYPE s_mandt,
        carrid    TYPE s_carr_id,
        carrname  TYPE s_carrname,
        url       TYPE s_carrurl,
    END OF ty_scarr .
TYPES:
    tt_scarr TYPE TABLE OF ty_scarr WITH EMPTY KEY .

DATA: gt_scarr TYPE tt_scarr.

DATA: iv_carrid   TYPE s_carr_id,
      iv_carrname TYPE s_carrname,
      iv_url      TYPE s_carrurl.

PARAMETERS: p_proc    RADIOBUTTON GROUP g1 DEFAULT 'X', " Method of AMDP-Proc "
            p_proc_c  RADIOBUTTON GROUP g1,             " Method of AMDP-Proc Call CDS "
            p_open    RADIOBUTTON GROUP g1,             " Method of Open SQL "
            p_func    RADIOBUTTON GROUP g1,             " Method of AMDP-Func "
            p_proc_f  RADIOBUTTON GROUP g1,             " Method of AMDP-Proc Call Func "
            p_open_c  RADIOBUTTON GROUP g1.             " Open SQL call CDS view "

START-OF-SELECTION.

  IF p_open_c EQ 'X'.
    SELECT * FROM ycds_admp_demo_scarr
    INTO CORRESPONDING FIELDS OF TABLE @gt_scarr.
    cl_demo_output=>display( gt_scarr ).   " 报错,改用ALV显示 "

  ELSE.

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

      TRY ."异常捕捉 "
        IF p_proc EQ 'X'.     " Method of AMDP-Proc "
          ycl_amdp_hdb_demo=>get_scarr(
            EXPORTING
              p_clnt       =  sy-mandt
            IMPORTING
              et_scarr = gt_scarr ).
        ENDIF.
        IF p_proc_c EQ 'X'.   " Method of AMDP-Proc Call CDS "
          ycl_amdp_hdb_demo=>get_scarr_by_cds(
            EXPORTING
              p_clnt       =  sy-mandt
            IMPORTING
              et_scarr = gt_scarr ).
        ENDIF.
        IF p_open EQ 'X'.     " Method of Open SQL "
          ycl_amdp_hdb_demo=>get_scarr_by_opensql(
            EXPORTING
              p_clnt       =  sy-mandt
              p_carrid     =  iv_carrid
              p_carrname   =  iv_carrname
              p_url        =  iv_url
            IMPORTING
              et_scarr = gt_scarr ).
        ENDIF.
        IF p_func EQ 'X'.     " Method of AMDP-Func, Dump, Not Allowed to call an AMDP Function Method "
          ycl_amdp_hdb_demo=>get_scarr_func(
            EXPORTING
              p_clnt       =  sy-mandt
            RECEIVING
              et_scarr = gt_scarr ).
        ENDIF.
        IF p_proc_f EQ 'X'.     " Method of AMDP-Proc Call Func "
          ycl_amdp_hdb_demo=>get_scarr_by_func(
            EXPORTING
              p_clnt       =  sy-mandt
            IMPORTING
              et_scarr = gt_scarr ).
        ENDIF.

        CATCH cx_amdp_error INTO DATA(amdp_error).
          cl_demo_output=>display( amdp_error->get_text( ) ).
          RETURN.
        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_scarr ).   " 报错,改用ALV显示 "
        "PERFORM frm_alv_show.
    ELSE.
      cl_demo_output=>display( '警告!当前系统不支持AMDP.' ).
    ENDIF.

  ENDIF.

附、AMDP异常

AMDP procedure 实现的异常名前缀是 CX_AMDP。这些异常都在目录 CX_DYNAMIC_CHECK 之下,必须使用 RASING 显式地在 AMDP procedure 实现的定义中声明。

CX_ROOT
|–CX_DYNAMIC_CHECK
| |–CX_AMDP_ERROR
| | |–CX_AMDP_VERSION_ERROR
| | | |–CX_AMDP_VERSION_MISMATCH
| | |–CX_AMDP_CREATION_ERROR
| | | |–CX_AMDP_CDS_CLIENT_MISMATCH
| | | |–CX_AMDP_DBPROC_GENERATE_FAILED
| | | |–CX_AMDP_DBPROC_CREATE_FAILED
| | | |–CX_AMDP_NATIVE_DBCALL_FAILED
| | | |–CX_AMDP_WRONG_DBSYS
| | |–CX_AMDP_EXECUTION_ERROR
| | | |–CX_AMDP_EXECUTION_FAILED
| | | |–CX_AMDP_IMPORT_TABLE_ERROR
| | | |–CX_AMDP_RESULT_TABLE_ERROR
| | |–CX_AMDP_CONNECTION_ERROR
| | | |–CX_AMDP_NO_CONNECTION
| | | |–CX_AMDP_NO_CONNECTION_FOR_CALL
| | | |–CX_AMDP_WRONG_CONNECTION

注意:AMDP function没有异常类。

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

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

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

相关文章

Linux自带10种常用性能分析与监控工具

liunx的性能分析与监控这些问题是一个很重要的问题&#xff0c;我们需要解决这个问题就可以借助liunx中的一些工具来帮我们处理掉这个问题&#xff0c;以下将会讲一下目前liunx中常用自带的性能分析与监控工具 Linux自带10种常用性能分析与监控工具1.vmstat2.iostat3.iotop监控…

uniapp cli的使用

uniapp官方文档有很多地方写的不是很明白。写笔记还是非常有必要的。 cli入门 uniapp的cli分为两种&#xff1a;uni cli和hbuilder cli。下面是官方对于两者的定义。官方实际上是更推荐uni cli的。因为官方文档通篇都是介绍uni cli&#xff0c;也是优先介绍uni cli的。hbuild…

Linux系统之Bonding 网卡绑定配置方法

Linux系统之Bonding 网卡绑定配置方法一、检查本地系统环境1.检查系统版本2.查看服务器网卡二、创建网卡配置文件1.进入网卡配置文件目录2.拷贝eth0的网卡配置文件3.修改bond0网卡配置文件4.修改eth1网卡配置文件5.修改eth2网卡配置文件三、创建bonding的配置文件1.编辑bonding…

OneFlow v0.9.0正式发布

今天是 OneFlow 开源的第 903 天&#xff0c;OneFlow v0.9.0 正式发布。本次更新包含 640 个 commit&#xff0c;完整更新列表请查看链接&#xff1a;https://github.com/Oneflow-Inc/oneflow/releases/tag/v0.9.0&#xff0c;欢迎下载体验新版本&#xff0c;期待你的反馈。One…

Java补充内容(Junit 反射 注解)

1 Junit测试 测试分类&#xff1a; 1. 黑盒测试&#xff1a;不需要写代码&#xff0c;给输入值&#xff0c;看程序是否能够输出期望的值。 2. 白盒测试&#xff1a;需要写代码的。关注程序具体的执行流程。 Junit使用&#xff1a;白盒测试 步骤&#xff1a; 定义一个测试类(测试…

机器学习知识总结——18.实现一个简单的K-Means聚类

文章目录引用库生成样本数据训练K-Means实验在上一章节里简要的介绍了无监督学习中聚类的知识点&#xff0c;看的太多理论概念&#xff0c;难免会有点莫名其妙&#xff0c;现在就让我们来实现一个简单的 K-Means 算法&#xff0c;从而从原理上彻底弄明白聚类是怎么工作的。 引…

YOLO v2主要看这些重点

来源&#xff1a;投稿 作者&#xff1a;ΔU 编辑&#xff1a;学姐 往期内容&#xff1a; YOLOv1学习笔记 论文 《YOLO9000:Better, Faster, Stronger》 Joseph Redmon∗†, Ali Farhadi∗† University of Washington∗ , Allen Institute for AI† http://pjreddie.com/…

计算机视觉OpenCv学习系列:第五部分、颜色操作

第五部分、颜色操作第一节、颜色表操作1.查找表LUT(look up table)2.颜色查找表&#xff08;1&#xff09;Gamma校正&#xff08;2&#xff09;OpenCV默认的查找表3.代码练习与测试&#xff08;1&#xff09;多种颜色查找表&#xff08;2&#xff09;滚动条颜色查找表第二节、随…

23种设计模式(十四)——中介者模式【接口隔离】

文章目录 意图什么时候使用中介者真实世界类比中介者模式的实现中介者模式的优缺点亦称:调解人、控制器、Intermediary、Controller、Mediator 意图 用一个中介者对象来封装一系列的对象交互。使得各对象不需要显式地相互引用,从而使其松散耦合,而且可以独立地改变它们之间…

新书预告:人机环境系统智能

东方算计&#xff1a;象者&#xff0c;像也西方计算&#xff1a;逻辑 or 实证人工智能是数学物理的产物&#xff0c;而数学是不完备的&#xff0c;物理仍是在探索中&#xff0c;所以人工智能存在着先天不足&#xff0c;有着大量的脆弱和缺点&#xff0c;具体而言&#xff0c;包…

7、矩阵的创建

目录 一、希尔伯特&#xff08;Hilbert&#xff09;矩阵 二、托普利兹&#xff08;Toeplitz&#xff09;矩阵 三、0&#xff5e;1间均匀分布的随机矩阵 四、标准正态分布随机矩阵 五、魔方矩阵 六、帕斯卡矩阵 七、范德蒙&#xff08;Vandermonde&#xff09;矩阵 MATLA…

机器学习——基本概念

小谈&#xff1a;一直想整理机器学习的相关笔记&#xff0c;但是一直在推脱&#xff0c;今天发现知识快忘却了&#xff08;虽然学的也不是那么深&#xff09;&#xff0c;但还是浅浅整理一下吧&#xff0c;便于以后重新学习。最近换到新版编辑器写文章了&#xff0c;有的操作挺…

跨平台freebasic集锦(1)-安装与概述

目录TIOBE Index for January 2023概述特点BASIC兼容性干净的语法多平台Unicode支持大量内置数据类型用户定义类型&#xff08;UDT&#xff09;默认过程参数值内联汇编Intel语法传统的预处理器支持调试支持创建OBJ、LIB、DLL和控制台或GUI EXE优化代码生成下载安装TIOBE Index …

Java设计模式-迭代器模式、迭代器模式是什么、怎么使用

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.9 迭代器者模式 6.9.1 定义 提供一个对象来顺序访问聚合对象中的一系列数据&#xff0c;而不暴露聚合对象的内部表示 6.9.2 结构 抽象聚合(Aggregate)角色&a…

[创业之路-48] :动态股权机制 -3- 静态股权分配 VS 动态股权分配

静态的股权分配是基础&#xff0c;动态的股权分配才是灵魂&#xff1a;只要你给了固态股权&#xff0c;比如说&#xff0c;股东A在最开始出资100万&#xff0c;占了10%的股份&#xff0c;但是&#xff0c;在后面的工作种&#xff0c;因为能力问题&#xff0c;价值观问题&#x…

回收租赁商城系统功能拆解12讲-会员权益

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

【自然语言处理】词袋模型在文本分类中的用法

词袋模型在文本分类中的用法1.加载数据 20 Newsgroups&#xff1a;数据被组织成 20 个不同的新闻组&#xff0c;每个新闻组对应一个不同的主题。一些新闻组彼此非常密切相关&#xff08;例如 comp.sys.ibm.pc.hardware / comp.sys.mac.hardware&#xff09;&#xff0c;而其他…

云原生之Docker容器的存储管理

一、检查本地docker环境 1.检查宿主机系统版本 [rootdocker ~]# cat /etc/centos-release CentOS Linux release 7.6.1810 (Core) 2.检查docker版本 [rootdocker ~]# docker -v Docker version 20.10.18, build b40c2f6二、创建一个测试httpd容器 1.创建测试目录 [rootdoc…

Python版本PathPlanning运动规划库中RotationToWorldFrame函数内部计算过程分析

本文主要对Python版本PathPlanning运动规划库中RotationToWorldFrame函数的内部计算过程分析&#xff0c;包括相关必备python基础和计算过程分析两部分&#xff0c;并给出了等效的MATLAB版本计算过程程序&#xff0c;方便分析对比。 &#xff08;注&#xff1a;RotationToWorld…

【春节旅游攻略】南京周边出发,小众又好玩的景点推荐

【写在前面】 过年了&#xff0c;今天咱不谈技术&#xff0c;聊聊轻松的话题&#xff0c;旅游&#xff0c;其实博主很喜欢去外面走走看的&#xff0c;特汇总了一个4天3晚的旅行攻略&#xff0c;说走就走&#xff0c;带上自己的亲人多看看外面的锦世繁华。 三人行&#xff0c;…