ABAP 动态查询条件

REPORT demo_select_dynamic_conditions .

DATA: cond(72) TYPE c,
itab LIKE TABLE OF cond.

PARAMETERS: city1(10) TYPE c, city2(10) TYPE c.

DATA wa TYPE spfli-cityfrom.

CONCATENATE'CITYFROM = ''' city1 ''''INTO cond.
APPEND cond TO itab.
CONCATENATE'OR CITYFROM = ''' city2 ''''INTO cond.
APPEND cond TO itab.
CONCATENATE'OR CITYFROM = ''' 'BERLIN' ''''INTO cond.
APPEND cond TO itab.

LOOP AT itab INTO cond.
WRITE cond.
ENDLOOP.

SKIP.

SELECT cityfrom
INTO wa
FROM spfli
WHERE (itab).

WRITE / wa.

ENDSELECT.

上一篇: ABAP 调试技巧

REPORT demo_select_dynamic_conditions .

DATA: cond(72) TYPE c,
itab LIKE TABLE OF cond.

PARAMETERS: city1(10) TYPE c, city2(10) TYPE c.

DATA wa TYPE spfli-cityfrom.

CONCATENATE'CITYFROM = ''' city1 ''''INTO cond.
APPEND cond TO itab.
CONCATENATE'OR CITYFROM = ''' city2 ''''INTO cond.
APPEND cond TO itab.
CONCATENATE'OR CITYFROM = ''' 'BERLIN' ''''INTO cond.
APPEND cond TO itab.

LOOP AT itab INTO cond.
WRITE cond.
ENDLOOP.

SKIP.

SELECT cityfrom
INTO wa
FROM spfli
WHERE (itab).

WRITE / wa.

ENDSELECT.

<think>我们被要求使用ABAP实现动态SQL查询动态SQL查询ABAP中通常用于在运行时构建和执行SQL语句,当表名、字段名或条件在编译时未知时非常有用。 在ABAP中,动态SQL查询可以通过以下几种方式实现: 1.使用`OPENCURSOR`和`FETCH`(对于SELECT语句)2.使用`CL_SQL_STATEMENT`类(推荐,更面向对象)3.直接使用`EXECSQL`(较少用,主要用于NativeSQL)但注意,动态SQL的使用需要谨慎,因为它可能带来安全风险(如SQL注入)和性能问题。下面我将重点介绍两种主要方法:###方法1:使用动态SELECT语句(内联声明) ABAP支持在运行时构建SELECT语句字符串,然后使用`INTO TABLE`等子句执行。```abapDATA:lv_tableTYPEstring VALUE'SFLIGHT',lt_whereTYPE string,lt_resultTYPETABLE OFsflight. "动态构建WHERE条件(注意防止注入) lt_where= `CARRID ='LH' ANDCONNID ='0400'`. "动态执行SELECTSELECT*FROM (lv_table)WHERE (lt_where)INTOTABLE @lt_result. ```###方法2:使用`CL_SQL_STATEMENT`类(更安全且功能强大) 这种方法使用ABAP的SQL包装类,可以防止SQL注入,并且支持参数绑定。 ```abapDATA: lo_stmtTYPE REFTO cl_sql_statement,lo_resultTYPEREF TOcl_sql_result_set,lv_sqlTYPE string,lt_whereTYPE string,lt_resultTYPE TABLEOF sflight,lx_sql_exTYPEREF TOcx_sql_exception."创建SQL语句对象lo_stmt =NEW cl_sql_statement( )."构建SQL语句(使用参数占位符) lv_sql ='SELECT *FROM sflight WHEREcarrid= ?AND connid =?'."执行查询并绑定参数TRY.lo_result =lo_stmt->execute_query(lv_sql).lo_result->set_param(EXPORTING value= 'LH')."绑定第一个参数lo_result->set_param( EXPORTINGvalue ='0400'). "绑定第二个参数"获取结果集到内表lo_result->into_table( IMPORTING data= lt_result )."关闭结果集lo_result->close( ).CATCHcx_sql_exception INTOlx_sql_ex."处理异常ENDTRY.``` ###动态指定表名和字段名如果需要动态指定表名和字段名,可以使用字符串拼接,但要注意防止SQL注入(避免直接使用用户输入拼接,或使用`CL_SQL_STATEMENT`的绑定机制)。 ```abapDATA: lv_tableTYPEstring VALUE'SFLIGHT',lv_fieldsTYPE stringVALUE 'CARRID,CONNID,FLDATE',lv_whereTYPE stringVALUE 'CARRID =''LH''',lt_resultTYPE REFTO data. FIELD-SYMBOLS: <lt_result> TYPEANYTABLE."创建动态内表结构(根据字段名)CREATE DATAlt_resultTYPE TABLEOF (lv_table). ASSIGN lt_result->* TO<lt_result>."动态执行SELECTSELECT (lv_fields) FROM(lv_table)INTOTABLE<lt_result>WHERE (lv_where).``` ###防止SQL注入-不要直接拼接用户输入的字符串到SQL语句中。-使用参数绑定(如`CL_SQL_STATEMENT`的`set_param`方法)。-使用`CL_ABAP_DYN_PRG`工具类来检查和转义输入。 ###性能考虑动态SQL可能会影响性能,因为数据库无法缓存执行计划。在频繁执行的场景中,尽量使用静态SQL。###相关ABAP语句和类-`SELECT... (fields) ...FROM(table) ...WHERE (condition)`:动态SELECT语法-`CL_SQL_STATEMENT`:执行动态SQL的类- `CL_SQL_RESULT_SET`:处理结果集- `CL_ABAP_DYN_PRG`:用于动态编程的工具类,提供检查输入的方法###示例:使用`CL_ABAP_DYN_PRG`检查输入```abapDATA: lv_tableTYPE string,lv_safe_tableTYPEstring.lv_table= 'SFLIGHT'."假设这是用户输入"检查表名是否有效lv_safe_table =cl_abap_dyn_prg=>check_table_name( lv_table). ```###总结在ABAP中实现动态SQL查询,推荐使用`CL_SQL_STATEMENT`类,因为它提供了参数绑定和异常处理,更安全。对于简单的动态表名和字段名,可以使用动态SELECT语法,但要确保输入的安全性。[^1]:SAP ABAP动态SQL官方文档[^2]:ABAPCDS视图开发指南§§相关问题§§1.如何防止ABAP动态SQL中的SQL注入攻击? 2.动态SQL与静态SQL在性能上有何差异? 3.如何使用ABAP动态SQL执行数据修改操作(INSERT/UPDATE/DELETE)?4.在SAP HANA环境中,动态SQL有哪些特殊注意事项?5.如何调试复杂的ABAP动态SQL程序?</think>### ABAP 实现动态 SQL 查询的方法 在 ABAP 中实现动态 SQL 查询主要通过以下技术实现,适用于表名、字段名或查询条件在运行时才能确定的场景: #### 1. **动态 SELECT 语法** ```abap DATA: lv_table TYPE string VALUE 'SFLIGHT', lv_where TYPE string VALUE `CARRID = 'LH'`. FIELD-SYMBOLS: <lt_data> TYPE ANY TABLE. " 创建动态内表 CREATE DATA lt_data TYPE TABLE OF (lv_table). ASSIGN lt_data->* TO <lt_data>. " 执行动态查询 SELECT * FROM (lv_table) INTO TABLE @<lt_data> WHERE (lv_where). ``` - **关键点**: - 使用 `( )` 包裹动态元素(表名/字段名/条件) - `FIELD-SYMBOLS` 和 `CREATE DATA` 处理动态结果集[^1] #### 2. **动态 JOIN 查询** ```abap DATA: lv_from TYPE string VALUE 'SFLIGHT AS f', lv_join TYPE string VALUE 'JOIN SPFLI AS p ON f~carrid = p~carrid', lv_where TYPE string VALUE `f~connid > '0400'`. SELECT * FROM (lv_from) (lv_join) INTO TABLE @DATA(lt_result) WHERE (lv_where). ``` #### 3. **CL_SQL_STATEMENT 类(面向对象方式)** ```abap DATA: lo_stmt TYPE REF TO cl_sql_statement, lo_result TYPE REF TO cl_sql_result_set, lv_sql TYPE string. lv_sql = |SELECT carrid, connid FROM sflight WHERE mandt = { sy-mandt }|. lo_stmt = NEW cl_sql_statement( ). lo_result = lo_stmt->execute_query( lv_sql ). lo_result->set_param( DATA(lt_result) ). lo_result->next_package( ). ``` - **优势**: - 支持参数绑定防止 SQL 注入 - 处理大数据集的分页获取[^2] #### 4. **动态条件生成(安全方式)** ```abab DATA(lo_dyn_prg) = cl_abap_dyn_prg=>get_instance( ). DATA(lv_safe_cond) = lo_dyn_prg->check_condition( iv_condition = 'CARRID = ''LH'' AND CONNID > 500' ). SELECT * FROM sflight INTO TABLE @DATA(lt_data) WHERE (lv_safe_cond). ``` - **安全机制**: - 使用 `CL_ABAP_DYN_PRG` 验证条件表达式 - 自动过滤危险字符如 `; DROP`[^3] #### 5. **ADBC 接口(高级数据库访问)** ```abap DATA: lo_conn TYPE REF TO cl_sql_connection, lo_stmt TYPE REF TO cl_sql_statement, lo_result TYPE REF TO cl_sql_result_set. lo_conn = cl_sql_connection=>get_connection( ). lo_stmt = lo_conn->create_statement( ). lo_stmt->set_param( REF #( p_carrid ) ). " 绑定输入参数 DATA(lv_sql) = `SELECT * FROM sflight WHERE carrid = ?`. lo_result = lo_stmt->execute_query( lv_sql ). lo_result->set_param( DATA(lt_result) ). ``` > **性能优化建议**: > 1. 对频繁执行的动态查询使用 **DB 视图预编译** > 2. 避免在循环中执行动态 SQL > 3. 使用 `UP TO n ROWS` 限制结果集大小 > 4. 复杂查询优先考虑 **CDS 视图** [^1]: ABAP 动态编程技术指南 [^2]: CL_SQL_STATEMENT 类文档 [^3]: ABAP SQL 注入防护最佳实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值