ABAP Help Document(24):11.3 Native SQL

11.3Native SQL

          实现Native SQL,1.使用ADBC classes;2.静态嵌入Native SQL。

Native SQL缺点:

1.创建的表没注册到R/3系统,在SAP字典中查找不到(se11),只能有Native SQL访问到;

2.没有自动控制MANDT,client字段需要手动处理;

3.动态执行的SQL存在安全隐患;

4.如果是只支持特定数据库的SQL语句,当底层数据库变化后,SQL语句就不再有效;

Native SQL优点:

1.可以根据数据库,使用特定高效的SQL语句;

2.可以访问到不在ABAP系统中的数据,例如:数据库系统表等;

1. ABAP Database Connectivity

          使用ADBC,没有自动client handling,操作时,需要明确指定mandt域值。

类:

CL_SQL_STATEMENT:执行SQL,只能相同参数执行一次,不能执行COMMIT,ROLLBACK;

方法:EXECUTE_DDL

执行CREATE,DROP,ALTER等操作;

方法:EXECUTE_UPDATE

执行INSERT,UPDATE,DELETE等操作;

方法:EXECUTE_QUERY

执行查询操作。返回result_set,对应类型CL_SQL_RESULT_SET;

方法:EXECUTE_PROCEDURE

执行procedure;

方法:SET_PARAM

设置参数,每个占位符?都需要执行一次;

方法:SET_PARAM_STRUCT

设置结构,结构中字段数必须和占位符数匹配,只执行一次;

方法:SET_PARAM_TABLE

设置table数据,table结构字段必须和占位符数匹配,只执行一次,只在INSERT,UPDATE,DELETE批量执行操作;

类:

CL_SQL_RESULT_SET:查询返回结果集;

方法:SET_PARAM

对单独行,列数据进行读取;

方法:SET_PARAM_STRUCT

读取行数据;

方法:SET_PARAM_TABLE

读取多行数据;

类:

CL_SQL_PREPARED_STATEMENT

执行SQL,可以传入不同参数,多次执行;

类:

CL_SQL_CONNECTION

连接其他数据库;

方法:GET_CONNECTION

获取数据表DBCAN中配置数据库链接;

方法:COMMIT

提交事务;

方法:ROLLBACK

回滚事务;

类:

CX_SQL_EXCEPTION

SQL异常类;

Attribute

Meaning

DB_ERROR

"X", if an SQL statement was not executed by DBMS. SQL_CODE and SQL_MESSAGE contain further information in this case.

DBOBJECT_EXISTS

"X", if you want to create a database object that already exists. DB_ERROR is also "X" in this case.

DBOBJECT_NOT_EXISTS

"X", if you want to access a database object that does not exist. DB_ERROR is also "X" in this case.

DUPLICATE_KEY

"X", if a DML statement would violate a unique table key. DB_ERROR is also "X" in this case.

INTERNAL_ERROR

Internal error code from DBMS. For further troubleshooting, see the log and trace files.

INVALID_CURSOR

"X", if you want to use an invalid or closed database cursor.

SQL_CODE

Database-specific error code, if DB_ERROR is "X".

SQL_MESSAGE

Database-specific error code, if DB_ERROR is "X".

示例:

"Native SQL
CLASS c_native_sql DEFINITION.
  PUBLIC SECTION.
    METHODS:constructor.
    METHODS:m_create_tab IMPORTING iv_tabname TYPE string RAISING cx_sql_exception.
    METHODS:m_insert IMPORTING iv_tabname TYPE string RAISING cx_sql_exception.
    METHODS:m_select IMPORTING iv_tabname TYPE string RAISING cx_sql_exception.
    METHODS:m_drop_tab IMPORTING iv_tabname TYPE string RAISING cx_sql_exception.
    "创建执行procedure
    METHODS:m_creat_proc.
    METHODS:m_excute_proc.
    "使用预定义sql
    METHODS:m_prepared_sql.
  PRIVATE SECTION.
    DATA:lo_sql_statement TYPE REF TO cl_sql_statement.
    DATA:lo_sql_prepared_statement TYPE REF TO cl_sql_prepared_statement.
    DATA:lo_sql_exception TYPE REF TO cx_sql_exception.
    TYPES:BEGIN OF s_tab,
           id TYPE N LENGTH 8,
           name TYPE C LENGTH 10,
           age TYPE I,
           address TYPE C LENGTH 20,
           zcount TYPE f,
          END OF s_tab.
    DATA:lt_tab TYPE TABLE OF s_tab.
    DATA:ls_tab LIKE LINE OF lt_tab.
ENDCLASS.
"类实现
CLASS c_native_sql IMPLEMENTATION.
  METHOD constructor.
    "实例化
    CREATE OBJECT lo_sql_statement.
    ls_tab-id = 3.
    ls_tab-name = 'lili'.
    ls_tab-age = 10.
    ls_tab-address = '四川'.
    ls_tab-zcount = '2023'.
    APPEND ls_tab TO lt_tab.
    ls_tab-id = 4.
    ls_tab-name = 'lucy'.
    ls_tab-age = 22.
    ls_tab-address = 'jack'.
    ls_tab-zcount = '1203.33'.
    APPEND ls_tab TO lt_tab.
  ENDMETHOD.
  "创建表
  METHOD m_create_tab.
    DATA:lv_statement TYPE string.
    "对应数据类型?
    "nvarchar,string,date,time,fltp,f不支持?
    "不知道支持哪些数据类型???
    "创建表
    lv_statement =  `CREATE TABLE `
    && iv_tabname
    && `( id char(8) NOT NULL,`
    && ` name varchar(10) NOT NULL,`
    && ` age int,`
    && ` address varchar(20),`
    && ` zcount float,`
*    && ` zdesc string,`
*    && ` creat_date date,`
*    && ` creat_time time,`
    && ` PRIMARY KEY (id) )`.
    lo_sql_statement->execute_ddl( lv_statement ).
  ENDMETHOD.
  "插入语句
  METHOD m_insert.
    DATA:lv_statement TYPE string.
    DATA:lv_rows TYPE I.
    DATA:lv_count TYPE I.
    DATA:lv_ref TYPE REF TO DATA.
    "循环插入
*    LOOP AT lt_tab INTO ls_tab.
*      CLEAR lv_statement.
*      "插入语句
*      lv_statement = `INSERT INTO ` && iv_tabname
*      && ` VALUES ('` && ls_tab-id && `','`
*      && ls_tab-name && `',`
*      && ls_tab-age &&  `,'`
*      && ls_tab-address &&  `','`
*      && ls_tab-zcount && `')`.
*      lv_rows = lo_sql_statement->execute_update( lv_statement ).
*      lv_count = lv_count + lv_rows.
*    ENDLOOP.
*    WRITE:/ lv_count.

    "绑定参数方式插入
    CLEAR lv_statement.
    "插入语句
    lv_statement = `INSERT INTO ` && iv_tabname
    && ` VALUES (?,?,?,?,?)`.
    "设置插入参数
    GET REFERENCE OF lt_tab INTO lv_ref.
    lo_sql_statement->set_param_table( lv_ref ).
    lv_rows = lo_sql_statement->execute_update( lv_statement ).
  ENDMETHOD.
  "查询语句
  METHOD m_select.
     DATA:lo_result TYPE REF TO cl_sql_result_set.
     DATA:lv_statement TYPE string.
     DATA:lt_table TYPE TABLE OF s_tab.
     DATA:ls_table LIKE LINE OF lt_table.
     DATA:lv_ref TYPE REF TO DATA.
     DATA:lv_val TYPE I.
     lv_statement = `SELECT COUNT(*) AS counts FROM ` && iv_tabname.
     "执行查询
     lo_result = lo_sql_statement->execute_query( lv_statement ).
     GET REFERENCE OF lv_val INTO lv_ref.
     lo_result->set_param( EXPORTING data_ref = lv_ref ).
     "返回单笔记录
     lo_result->next( ).
     WRITE:/ lv_val.

     "执行查询
     lv_statement = `SELECT * FROM ` && iv_tabname.
     lo_result = lo_sql_statement->execute_query( lv_statement ).
     GET REFERENCE OF lt_table INTO lv_ref.
     lo_result->set_param_table( EXPORTING itab_ref = lv_ref ).
     "返回多笔记录
     lo_result->next_package( ).
     LOOP AT lt_table INTO ls_table.
       WRITE:/ ls_table-name,ls_table-age,ls_table-address,ls_table-zcount.
     ENDLOOP.

     "参数绑定使用占位符
     DATA:lv_address TYPE C LENGTH 20 VALUE '重庆'.
     DATA:lv_age TYPE I VALUE 20.
     CLEAR lt_table[].
     lv_statement = `SELECT * FROM ` && iv_tabname
     && ` WHERE address = ? AND age > ?`.
     "绑定参数,每个?占位符
     GET REFERENCE OF lv_address INTO lv_ref.
     lo_sql_statement->set_param( lv_ref ).
     GET REFERENCE OF lv_age INTO lv_ref.
     lo_sql_statement->set_param( lv_ref ).
     "查询结果
     lo_result = lo_sql_statement->execute_query( lv_statement ).
     GET REFERENCE OF lt_table INTO lv_ref.
     lo_result->set_param_table( EXPORTING itab_ref = lv_ref ).
     lo_result->next_package( ).
     LOOP AT lt_table INTO ls_table.
       WRITE:/ ls_table-name,ls_table-age,ls_table-address,ls_table-zcount.
     ENDLOOP.
  ENDMETHOD.
  METHOD m_drop_tab.
    DATA:lv_statement TYPE string.
    "删除表
    lv_statement =  `DROP TABLE ` && iv_tabname.
    lo_sql_statement->execute_ddl( lv_statement ).
  ENDMETHOD.
  "创建procedure
  METHOD m_creat_proc.
    DATA:lv_statement TYPE string.
    DATA:lv_inc TYPE P LENGTH 7 DECIMALS 2.
    DATA:lv_ref TYPE REF TO DATA.
    lv_statement = `CREATE PROCEDURE  `
    && `ZTOM_TEST_PROC(IN inc DECIMAL(15,2)) AS BEGIN `
    && `UPDATE sflight SET price = price + :inc;`
    && `END`.
    GET REFERENCE OF lv_inc INTO lv_ref.
    lo_sql_statement->set_param(
      data_ref = lv_ref
      inout = cl_sql_statement=>c_param_in ).
    lo_sql_statement->execute_ddl( lv_statement ).
  ENDMETHOD.
  "执行procedure
  METHOD m_excute_proc.
    DATA:lv_rows TYPE I.
    lv_rows = lo_sql_statement->execute_procedure( proc_name = 'ZTOM_TEST_PROC' ).
  ENDMETHOD.
  "执行预定义SQL
  METHOD m_prepared_sql.
    DATA:lv_statement TYPE string.
    DATA:lt_scarr TYPE TABLE OF scarr.
    DATA:ls_scarr LIKE LINE OF lt_scarr.
    DATA:lt_carrid TYPE TABLE OF scarr-carrid.
    DATA:lv_carrid TYPE scarr-carrid.
    DATA:lv_ref TYPE REF TO DATA.
    "结果
    DATA:lo_result TYPE REF TO cl_sql_result_set.
    lv_carrid = 'AA'.
    APPEND lv_carrid TO lt_carrid.
    lv_carrid = 'AB'.
    APPEND lv_carrid TO lt_carrid.

    lv_statement = 'SELECT * FROM SCARR WHERE CARRID = ?'.
    CREATE OBJECT lo_sql_prepared_statement
      EXPORTING
        statement = lv_statement.
    "获取参数
    GET REFERENCE OF lv_carrid INTO lv_ref.
    lo_sql_prepared_statement->set_param( lv_ref ).
    LOOP AT lt_carrid INTO lv_carrid.
      lo_result = lo_sql_prepared_statement->execute_query( ).
      GET REFERENCE OF lt_scarr INTO lv_ref.
      lo_result->set_param_table( EXPORTING itab_ref = lv_ref ).
      lo_result->next_package( ).
      LOOP AT lt_scarr INTO ls_scarr.
        WRITE:/ ls_scarr-carrid,ls_scarr-carrname,ls_scarr-url.
      ENDLOOP.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

2.Static Embedding Native SQL

          静态嵌入Native SQL语句。

语法:

EXEC SQL.
ENDEXEC.

示例:

"嵌入sql
FORM f_embeded_sql.
  DATA:lo_exception TYPE REF TO cx_root.
  DATA: p_carrid TYPE spfli-carrid VALUE 'AA',
        p_connid TYPE spfli-connid VALUE '0017'.
  TYPES: BEGIN OF s_wa,
          cityfrom TYPE spfli-cityfrom,
          cityto   TYPE spfli-cityto,
        END OF s_wa.
  DATA:lt_wa TYPE TABLE OF s_wa.
  DATA:ls_wa LIKE LINE OF lt_wa.
  DATA:lt_spfli TYPE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF lt_spfli.
  DATA:lv_carrid TYPE spfli-carrid.
  DATA:lv_connid TYPE spfli-connid.

  TRY.
    "执行sql,使用:使用本地或全局变量
    EXEC SQL.
      SELECT cityfrom, cityto
             INTO STRUCTURE :ls_wa
             FROM spfli
             WHERE mandt  = :sy-mandt
              AND carrid = :p_carrid
              AND connid = :p_connid
    ENDEXEC.
    WRITE:/ ls_wa-cityfrom,ls_wa-cityto.

    "使用cursor
    "游标
    DATA:lv_c1 TYPE cursor.
    EXEC SQL.
      OPEN lv_c1 FOR SELECT * FROM spfli
    ENDEXEC.
    DO.
      EXEC SQL.
        FETCH NEXT lv_c1 INTO :lv_carrid, :lv_connid
      ENDEXEC.
      IF sy-subrc <> 0.
        EXIT.
      ELSE.
        WRITE:/ lv_carrid,lv_connid.
      ENDIF.
    ENDDO.
    "关闭游标
    EXEC SQL.
      CLOSE lv_c1
    ENDEXEC.

     "创建procedure
     DATA:incprice TYPE P LENGTH 8 DECIMALS 2 VALUE '-10.00'.
     "创建procedure
     EXEC SQL.
       CREATE OR REPLACE PROCEDURE update_price (x IN NUMBER) IS
       BEGIN
         UPDATE sflight SET price = price + x WHERE carrid = 'AA' AND connid = '0017';
       END;
     ENDEXEC.
     "执行procedure
     EXEC SQL.
       EXECUTE PROCEDURE update_price ( IN :incprice )
     ENDEXEC.
     "删除procedure
     EXEC SQL.
       DROP PROCEDURE update_price
     ENDEXEC.

     "创建function,有问题
     DATA:lv_scarrname TYPE C LENGTH 20.
     DATA:lv_scarrid TYPE C LENGTH 3 VALUE 'AA'.
     "创建function
     EXEC SQL.
        CREATE FUNCTION func1( input CHAR(3) )
        RETURNING char(20);
        DEFINE output char(20);
        SELECT carrname
               INTO output
               FROM scarr
               WHERE carrid = input;
        RETURN output;
        END FUNCTION;
     ENDEXEC.
     "执行function
     EXEC SQL.
       EXECUTE PROCEDURE func1( IN  :lv_scarrid, OUT :lv_scarrname )
     ENDEXEC.
     WRITE:/ lv_scarrname.
     "删除function
     EXEC SQL.
       DROP FUNCTION func1
     ENDEXEC.
  CATCH cx_root INTO lo_exception.
    DATA:lv_string TYPE string.
    lv_string = lo_exception->get_text( ).
    MESSAGE lv_string TYPE 'E'.
  ENDTRY.
ENDFORM.

3.Object Service

          使用面向对象框架,处理关系数据库。

1.Persistence service,持久层服务

2.Transaction service,传输层服务

3.Query service,查询层服务

持久层类:

创建持久记录,示例:DEMO_CREATE_PERSISTENT。

CL_persistent:创建持久层类型,示例持久类:CL_SPFLI_PERSISTENT。

CA_persistent:类代理,示例:CA_APFLI_PERSISTENT。

CB_persistent:所有actor的父类,例如:CL_OS_CA_COMMON

类方法:

CREATE_PERSISTENT:创建持久对象。不会判断是否持久对象已经创建,使用GET_PERSISTENT判断是否对象已经创建;

GET_PERSISTENT:获取已经存在持久对象;

DELETE_PERSISTENT:删除持久对象;

CREATE_TRANSIENT:生成持久对象的临时对象;

GET_TRANSIENT:获取持久对象的临时对象;

持久类代理接口:

IF_OS_FACTORY:

接口方法:

IF_OS_FACTORY~CREATE_PERSISTENT:创建持久对象。

IF_OS_FACTORY~CREATE_PERSISTENT_BY_KEY:创建持久对象,通过GUID key;

IF_OS_FACTORY~REFRESH_PERSISTENT:强制系统将持久对象的当前属性从数据库加载到ABAP程序中;

IF_OS_FACTORY~DELETE_PERSISTENT:删除持久对象;

IF_OS_FACTORY~CREATE_TRANSIENT;

IF_OS_FACTORY~CREATE_TRANSIENT_BY_KEY;

IF_OS_FACTORY~RELEASE:从持久性服务的管理中完全删除由类代理管理的对象;

IF_OS_CA_PERSISTENCY:

接口方法:

IF_OS_CA_PERSISTENCY~GET_PERSISTENT_BY_OID;

IF_OS_CA_PERSISTENCY~GET_PERSISTENT_BY_KEY;

IF_OS_CA_PERSISTENCY~GET_PERSISTENT_BY_OID_TAB;

IF_OS_CA_PERSISTENCY~GET_PERSISTENT_BY_KEY_TAB;

IF_OS_CA_PERSISTENCY~GET_PERSISTENT_BY_QUERY;

IF_OS_CA_INSTANCE:

接口方法:

IF_OS_CA_INSTANCE~GET_STATUS:获取托管对象的管理状态,状态代码Type Group: OSCON,结构OSTATUS_xxx;

IF_OS_CA_INSTANCE~GET_NOT_LOADED;

IF_OS_CA_INSTANCE~GET_CREATED;

IF_OS_CA_INSTANCE~GET_LOADED;

IF_OS_CA_INSTANCE~GET_CHANGED;

IF_OS_CA_INSTANCE~GET_DELETED;

IF_OS_CA_INSTANCE~TRANSIENT;

状态代码:

OSCON_OSTATUS_NOT_LOADED

0

Representative object for a persistent object, data not yet loaded from the database.

OSCON_OSTATUS_NEW

1

The object is persistent and is newly created.

OSCON_OSTATUS_LOADED

2

The object is persistent and has been loaded completely.

OSCON_OSTATUS_CHANGED

3

The object is persistent and has been changed.

OSCON_OSTATUS_DELETED

4

The object is persistent and has been deleted.

OSCON_OSTATUS_TRANSIENT

10

The object is transient.

OSCON_OSTATUS_LOADING

12

The object is being loaded at this moment.

持久类管理接口:

IF_OS_STATE

接口方法:

IF_OS_STATE~INIT;

IF_OS_STATE~INVALIDATE;

IF_OS_STATE~HANDLE_EXCEPTION;

IF_OS_STATE~GET and IF_OS_STATE~SET;

传输层类:

用来更新数据库记录,示例:DEMO_TRANSACTION_SERVICE。使用系统类CL_OS_SYSTEM,调用GET_TRANSACTION_MANAGER方法,

使用接口IF_OS_TRANSACTION_MANAGER and IF_OS_TRANSACTION,访问事务管理器和事务。

CL_OS_SYSTEM:

类方法:

INIT_AND_SET_MODES:初始化对象服务,创建服务对象,只执行一次;

指定可能的模式:

OSCON_DMODE_DEFAULT, OSCON_DMODE_UPDATE_TASK, OSCON_DMODE_UPDATE_TASK_SYNC and OSCON_DMODE_LOCAL for local updates
OSCON_DMODE_DIRECT for saving directly;

GET_TRANSACTION_MANAGER:返回事务管理器,接口类型:IF_OS_QUERY_MANAGER;

接口IF_OS_QUERY_MANAGER方法:

IF_OS_TRANSACTION_MANAGER~CREATE_TRANSACTION:返回事务接口类型:IF_OS_TRANSACTION;

IF_OS_TRANSACTION_MANAGER~GET_CURRENT_TRANSACTION:返回当前事务;

IF_OS_TRANSACTION_MANAGER~GET_TOP_TRANSACTION:返回最高等级事务;

接口IF_OS_TRANSACTION方法:

IF_OS_TRANSACTION~START:执行事务,没有其他事务,等级变成top;

IF_OS_TRANSACTION~END:停止事务;

IF_OS_TRANSACTION~UNDO;

IF_OS_TRANSACTION~END_AND_CHAIN;

IF_OS_TRANSACTION~UNDO_AND_CHAIN;

IF_OS_TRANSACTION~REGISTER_CHECK_AGENT;

IF_OS_TRANSACTION~GET_STATUS;

IF_OS_TRANSACTION~SET_MODE_UNDO_RELEVANT;

IF_OS_TRANSACTION~SET_MODE_UPDATE;

IF_OS_TRANSACTION~GET_MODES;

IF_OS_TRANSACTION~SAVE_REQUESTED;

IF_OS_TRANSACTION~SAVE_PREPARED;

IF_OS_TRANSACTION~FINISHED;

查询层类:

通过逻辑表达式查询持久层对象,示例:DEMO_QUERY_SERVICE。通过CL_OS_SYSTEM类方法GET_QUERY_MANAGER获取查询管理器。IF_OS_QUERY_MANAGER, IF_OS_QUERY, and IF_OS_QUERY_FACTORY等接口操作查询管理器。

CL_OS_SYSTEM类方法:GET_QUERY_MANAGER返回查询管理器,类型IF_OS_QUERY_MANAGER;

IF_OS_QUERY_MANAGER:

接口方法:

IF_OS_QUERY_MANAGER~CREATE_QUERY;

IF_OS_QUERY:

接口方法:

IF_OS_QUERY~GET_EXPR_FACTORY,返回IF_OS_QUERY_EXPR_FACTORY类型;

IF_OS_QUERY~SET_FILTER_EXPR,设置筛选条件逻辑表达式;

IF_OS_QUERY~SET_PARAMETERS_EXPR,设置筛选条件参数列表;

IF_OS_QUERY~SET_ORDERING_EXPR,设置排序规则;

IF_OS_QUERY~PARSE,创建筛选条件,排序等内表显示;

IF_OS_QUERY_EXPR_FACTORY:

接口方法:

IF_OS_QUERY_EXPR_FACTORY~CREATE_OPERATOR_EXPR:创建比较条件,参数:I_ATTR, I_OPERATOR and I_ATTR2.。

IF_OS_QUERY_EXPR_FACTORY~CREATE_LIKE_EXPR:创建like条件,参数:I_ATTR, I_PATTERN,I_NOT;

IF_OS_QUERY_EXPR_FACTORY~CREATE_ISNULL_EXPR:创建是否为空条件,参数:I_ATTR,I_NOT(是否为空);

IF_OS_QUERY_EXPR_FACTORY~CREATE_REF_EXPR:创建是否ref相等,参数:I_ATTR,ref使用参数I_IDX指定;

IF_OS_QUERY_EXPR_FACTORY~CREATE_NOT_EXPR:创建not条件;

IF_OS_QUERY_EXPR_FACTORY~CREATE_AND_EXPR:创建AND条件;

IF_OS_QUERY_EXPR_FACTORY~CREATE_OR_EXPR:创建OR条件;

IF_OS_QUERY_EXPR_FACTORY~CREATE_PARAMETERS_EXPR:参数列表,返回IF_OS_QUERY_PARAMETERS_EXPR类型;

IF_OS_QUERY_EXPR_FACTORY~CREATE_ORDERING_EXPR:排序列表,返回

IF_OS_QUERY_ORDERING_EXPR类型;

原文地址:https://www.cnblogs.com/tangToms/p/14696751.html