可使用 CL_SQL_STATEMENT
类的以下实例方法执行查询:
EXECUTE_QUERY
该方法有一个字符串类型的强制输入参数 STATEMENT
,必须向其传递语法正确的 SELECT
语句。与 DML 语句一样,SET_PARAM
方法可用于将 ABAP 数据对象绑定到占位符。
查询结果将在返回值 RESULT_SET
中返回对 CL_SQL_RESULT_SET
类对象的引用。该对象的方法允许访问查询的结果集。为了在数据库 LUW 结束后保留结果集,可以在 EXECUTE_QUERY
方法的输入参数 HOLD_CURSOR
中填入 X。
结果对象的 CL_SQL_RESULT_SET
类提供了以下用于将结果集读入 ABAP 数据对象的实例方法,
SET_PARAM, NEXT, 和 CLOSE
这三个方法可访问结果集中的单个行和列:
SET_PARAM
:使用SET_PARAM
,必须通过向该方法传递每列的相应数据引用,从左到右为列分配兼容的 ABAP 数据对象。NEXT
:NEXT
用于逐个寻址结果集中的行。如果可以寻址该行,则返回值为 1,否则为 0。CLOSE
:
使用CLOSE
关闭读取。如果要修改两次调用NEXT
之间的参数绑定,必须先调用CLEAR_PARAMETERS
方法。
SET_PARAM_STRUCT、NEXT 和 CLOSE
这些方法提供了对结果集中各行的访问。
使用 SET_PARAM_STRUCT
方法,必须通过向方法传递相应的数据引用,为结果集的行分配完全兼容的 ABAP 结构。可以将指定要读取的列的名称和顺序的内部表传递给参数 CORRESPONDING_FIELDS
。其余方法与 SET_PARAM
方法相同。
SET_PARAM_TABLE、NEXT_PACKAGE 和 CLOSE
这些方法可以访问结果集中的多行。
使用 SET_PARAM_TABLE
,必须通过向该方法传递相应的数据引用,为结果集的行分配一个结构完全兼容的内部表。与 SET_PARAM_STRUCT
一样,CORRESPONDING_FIELDS
参数用于指定要传送的列。
这里使用 NEXT_PACKAGE
代替 NEXT
,最多读取传递给输入参数 UPTO
的行数。如果没有向 UPTO
传递任何值,则会读取所有行。在每次调用 NEXT_PACKAGE
时,读取的记录都会追加到内部表中,不会删除之前的内容,读取的记录数会在返回值 ROWS_RET
中返回。在更改参数绑定和 CLOSE
时,情况与 SET_PARAM
相同。
如果查询返回一个以上的结果集,上述方法默认访问第一个结果集,NEXT_RESULT_SET
方法可用于切换到下一个结果集。对于每个结果集,必须再次使用上述 SET_...
方法才能附加数据到 ABAP 数据对象。
提示
- 可以将 ABAP 字典中内置类型为 INT2 的指示变量的数据引用传递给
SET_PARAM
方法的可选输入参数IND_REF
。在该数据引用中,值-1
表示数据库中是否存在空值。 - 出于安全考虑,最好使用占位符
?
来设置查询参数,而不是连接动态内容。这也是防止 SQL 注入的一种方法。如果语句只包含程序中的静态内容,而程序外的动态内容只能在操作符位置使用占位符,并且语句不能从外部修改。 - 在数据库表中的字段和 ABAP 数据对象之间进行赋值时,ABAP 类型和数据库类型之间会发生映射。ABAP 类型应与数据库类型相匹配。如果不匹配,则必须在本地 SQL 接口中进行转换。这些转换与平台有关,并可能引发异常。
EXECUTE_QUERY
方法也可用于调用存储过程。在符合要求的数据库中,内部表等可以绑定到结果集。EXECUTE PROCEDURE
方法则无法做到这一点(请参阅该方法下的示例)。- 通用方法
EXECUTE
也有一个CL_SQL_RESULT_SET
类型的返回值,其使用方法与EXECUTE_QUERY
相同。 - 在调用具有多个输出参数的数据库存储过程时,可能会出现多个结果。
示例 1:读取数据到工作区
使用 ADBC 从之前使用 ABAP SQL 填充的数据库表中按顺序读取行到工作区。
ABAP
DELETE FROM demo_update.
INSERT demo_update FROM TABLE @(
VALUE #( ( id = 'X' col1 = 1 col2 = 2 col3 = 3 col4 = 4 )
( id = 'Y' col1 = 5 col2 = 6 col3 = 7 col4 = 8 ) ) ).
DATA result TYPE demo_update.
TRY.
FINAL(query) = NEW cl_sql_statement( )->execute_query(
`SELECT client, id, col1, col2, col3, col4 ` &&
` FROM demo_update ` &&
` WHERE client = '` && sy-mandt && `' ` ).
query->set_param_struct( struct_ref = REF #( result ) ).
WHILE query->next( ) > 0.
cl_demo_output=>write( result ).
ENDWHILE.
query->close( ).
CATCH cx_sql_exception INTO FINAL(exc).
cl_demo_output=>display( exc->get_text( ) ).
RETURN.
ENDTRY.
cl_demo_output=>display( ).
示例2:读取数据到内表
ABAP
DELETE FROM demo_update.
INSERT demo_update FROM TABLE @(
VALUE #( ( id = 'X' col1 = 1 col2 = 2 col3 = 3 col4 = 4 )
( id = 'Y' col1 = 5 col2 = 6 col3 = 7 col4 = 8 ) ) ).
DATA result TYPE TABLE OF demo_update WITH EMPTY KEY.
TRY.
FINAL(query) = NEW cl_sql_statement( )->execute_query(
`SELECT client, id, col1, col2, col3, col4 ` &&
` FROM demo_update ` &&
` WHERE client = '` && sy-mandt && `' ` ).
query->set_param_table( itab_ref = REF #( result ) ).
query->next_package( ).
query->close( ).
CATCH cx_sql_exception INTO FINAL(exc).
cl_demo_output=>display( exc->get_text( ) ).
RETURN.
ENDTRY.
cl_demo_output=>display( result )
还有三个官方可以执行的 Demo,通过 SE38 运行下列程序:
DEMO_ADBC_QUERY
:ADBC 查询示例,类CL_SQL_STATEMENT
中的EXECUTE_QUERY
方法用于读取当前客户端的数据库表SFLIGHT
中的三列。使用CL_SQL_RESULT_SET
类中的SET_PARAM_TABLE
方法将一个适当的内部表绑定到结果集中。使用NEXT_PACKAGE
方法将结果集中的所有行传送到内部表。DEMO_ADBC_DDL_DML
:该程序可创建一个数据库表,其名称可由用户选择。之后,可以向数据库表中插入 100 条记录,读取单个记录,并再次删除数据库表。本地 SQL 语句使用字符串表达式传递给CL_SQL_STATEMENT
类的方法。DEMO_ADBC_DDL_DML_BULK_ACCESS
:该程序可创建和删除数据库表,表名可由用户选择。可以向数据库表中插入行、再次删除行、读取所有行并再次删除数据库表在 DML 语句的所有方法中,参数都使用内部表绑定。- 插入(insert)会将内部表中的所有行写入数据库表中,而该表的键值尚未存在。
- 删除(delete)数据库表中键值出现在内部表中的所有记录。
- 查询(select )将数据库表中所有行的查询结果集读入内部表。
参考文档: