关于 abap-sql-amdp
abap-sql-amdp 是面向 ABAP 开发者的 SQL 与 AMDP 指南,覆盖现代查询语法、数据库过程及 Clean Core 使用边界。
主要功能
- 01现代 ABAP SQL 查询语法参考
- 02窗口函数、CTE 与集合操作示例
- 03AMDP 过程和 CDS 表函数指导
- 04说明 PRIVILEGED ACCESS 的用途
- 05按 Clean Core 等级评估 SQL 做法
适用场景
- 01编写或优化 ABAP SQL 查询
- 02实现 AMDP 过程或 CDS 表函数
- 03评估直接访问 SAP 数据库表的影响
- 04将旧代码迁移至 ABAP SQL 或 AMDP
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ likweitan/ abap-skills --skill abap-sql-amdp安装后在 Claude Code 中输入/abap-sql-amdp确认已加载。
附带文件references/sql-functions-reference.md
详细介绍
ABAP SQL 与 AMDP
在 ABAP Cloud 和 Standard ABAP 中编写现代 ABAP SQL 语句和 ABAP Managed Database Procedures(AMDP)的指南。
Clean core 上下文:从已发布的 CDS 视图执行
SELECT属于 Level A。直接对 SAP 数据库表进行读取属于 Level C(ATC 优先级 2);直接写入属于 Level D(ATC 优先级 1)。EXEC SQL(原生 SQL)是关键语句 → Level D。SYCM_USAGE_OF_APIS会报告针对 SAP 数据库表和视图的 SQL 语句。有关级别的详细信息,请参阅abap-cloud技能。
工作流
-
确定用户的目标:
- 编写或优化 ABAP SQL 查询
- 使用高级 SQL 功能(窗口函数、CTE、聚合)
- 创建 AMDP 过程或函数
- 通过 AMDP 实现 CDS 表函数
- 了解用于绕过授权检查的 PRIVILEGED ACCESS
-
识别上下文:
- ABAP for Cloud Development 还是 Standard ABAP(影响可用语法)
- 性能优化需求
- AMDP 是否合理(尽可能优先使用 ABAP SQL)
-
使用现代 ABAP SQL 语法指导实现
现代 ABAP SQL 速查
使用内联声明的基本 SELECT
"Single record
SELECT SINGLE FROM ztravel
FIELDS travel_id, description, total_price, currency_code
WHERE travel_id = @lv_travel_id
INTO @DATA(ls_travel).
"Multiple records into internal table
SELECT FROM ztravel
FIELDS travel_id, description, total_price, currency_code
WHERE status = 'O'
ORDER BY total_price DESCENDING
INTO TABLE @DATA(lt_travels)
UP TO 100 ROWS.
SELECT 列表中的表达式
SELECT FROM zflight
FIELDS carrier_id,
connection_id,
flight_date,
seats_max - seats_occupied AS seats_free,
CASE WHEN seats_occupied > seats_max * 80 / 100
THEN 'FULL'
ELSE 'AVAILABLE'
END AS availability,
CAST( price AS DECFLOAT34 ) AS price_dec,
CONCAT( carrier_id, connection_id ) AS flight_key
INTO TABLE @DATA(lt_flights).
聚合函数和 GROUP BY
SELECT FROM zflight
FIELDS carrier_id,
COUNT(*) AS flight_count,
SUM( seats_occupied ) AS total_passengers,
AVG( price ) AS avg_price,
MIN( flight_date ) AS first_flight,
MAX( flight_date ) AS last_flight
GROUP BY carrier_id
HAVING COUNT(*) > 10
INTO TABLE @DATA(lt_stats).
窗口函数
SELECT FROM zflight
FIELDS carrier_id,
connection_id,
flight_date,
price,
"Running total
SUM( price ) OVER( PARTITION BY carrier_id
ORDER BY flight_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS running_total,
"Row number within partition
ROW_NUMBER( ) OVER( PARTITION BY carrier_id
ORDER BY flight_date DESCENDING ) AS row_num,
"Ranking
RANK( ) OVER( PARTITION BY carrier_id ORDER BY price DESCENDING ) AS price_rank,
"Lead/Lag
LAG( price, 1 ) OVER( PARTITION BY carrier_id ORDER BY flight_date ) AS prev_price,
LEAD( price, 1 ) OVER( PARTITION BY carrier_id ORDER BY flight_date ) AS next_price
INTO TABLE @DATA(lt_window).
公用表表达式(CTE)
WITH
+connections AS (
SELECT FROM zflsch
FIELDS carrier_id, connection_id, city_from, city_to
WHERE carrier_id IN @lt_carriers ),
+flight_counts AS (
SELECT FROM zflight
FIELDS carrier_id, connection_id,
COUNT(*) AS cnt
GROUP BY carrier_id, connection_id ),
+result AS (
SELECT FROM +connections AS c
INNER JOIN +flight_counts AS f
ON c~carrier_id = f~carrier_id AND c~connection_id = f~connection_id
FIELDS c~carrier_id, c~city_from, c~city_to, f~cnt )
SELECT FROM +result
FIELDS *
ORDER BY cnt DESCENDING
INTO TABLE @DATA(lt_result).
集合运算(UNION、INTERSECT、EXCEPT)
"UNION ALL (keeps duplicates) / UNION (removes duplicates)
SELECT FROM ztable1 FIELDS col1, col2
UNION ALL
SELECT FROM ztable2 FIELDS col1, col2
INTO TABLE @DATA(lt_union).
"INTERSECT — rows in both
SELECT FROM ztable1 FIELDS col1
INTERSECT
SELECT FROM ztable2 FIELDS col1
INTO TABLE @DATA(lt_intersect).
"EXCEPT — rows in first but not second
SELECT FROM ztable1 FIELDS col1
EXCEPT
SELECT FROM ztable2 FIELDS col1
INTO TABLE @DATA(lt_except).
PRIVILEGED ACCESS
绕过 CDS 访问控制(DCL)——请谨慎使用:
"Skips access control defined in CDS DCL
SELECT FROM zi_travel
FIELDS travel_id, description
WHERE status = 'O'
INTO TABLE @DATA(lt_all_travels)
PRIVILEGED ACCESS.
内置 SQL 函数
| 类别 | 函数 |
|---|---|
| 字符串 | CONCAT、SUBSTRING、LENGTH、LEFT、RIGHT、LTRIM、RTRIM、UPPER、LOWER、REPLACE、LPAD、RPAD |
| 数值 | ABS、CEIL、FLOOR、ROUND、MOD、DIV、DIVISION |
| 日期/时间 | DATS_ADD_DAYS、DATS_DAYS_BETWEEN、TSTMP_ADD_SECONDS、TSTMP_CURRENT_UTCTIMESTAMP、DATN_ADD_MONTHS |
| 转换 | CAST、COALESCE、CURRENCY_CONVERSION、UNIT_CONVERSION |
| 空值 | COALESCE、CASE WHEN ... IS NULL |
| 聚合 | COUNT、SUM、AVG、MIN、MAX、STRING_AGG |
子查询
"Scalar subquery
SELECT FROM ztravel
FIELDS travel_id,
total_price,
( SELECT AVG( total_price ) FROM ztravel ) AS avg_price
INTO TABLE @DATA(lt_with_avg).
"EXISTS subquery
SELECT FROM ztravel AS t
FIELDS t~travel_id, t~description
WHERE EXISTS ( SELECT FROM zbooking AS b
WHERE b~travel_id = t~travel_id
AND b~flight_date > @sy-datum )
INTO TABLE @DATA(lt_with_bookings).
AMDP(ABAP Managed Database Procedures)
何时使用 AMDP
- 大多数场景优先使用 ABAP SQL
- 在以下情况下使用 AMDP:复杂计算可通过 SQLScript 获益、需要 CDS 表函数,或大规模数据处理需要数据库级优化
AMDP 类结构
CLASS zcl_my_amdp DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb. "Mandatory for AMDP
TYPES: BEGIN OF ty_result,
carrier_id TYPE s_carr_id,
total TYPE i,
END OF ty_result,
tt_result TYPE STANDARD TABLE OF ty_result WITH EMPTY KEY.
"AMDP procedure
METHODS get_carrier_stats
AMDP OPTIONS READ-ONLY CDS SESSION CLIENT DEPENDENT
EXPORTING VALUE(et_result) TYPE tt_result.
"AMDP table function for CDS table function
CLASS-METHODS get_data FOR TABLE FUNCTION zdemo_amdp_tf.
ENDCLASS.
AMDP 过程实现
METHOD get_carrier_stats
BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zflight_ve.
et_result = SELECT carrier_id,
COUNT(*) AS total
FROM zflight_ve
GROUP BY carrier_id
ORDER BY total DESC;
ENDMETHOD.
用于 CDS 表函数的 AMDP 表函数
CDS 表函数定义:
@ClientHandling.type: #CLIENT_DEPENDENT
@ClientHandling.algorithm: #SESSION_VARIABLE
define table function ZDEMO_AMDP_TF
with parameters @Environment.systemField: #SYSTEM_LANGUAGE p_lang : abap.lang
returns {
key carrier_id : s_carr_id;
carrier_name : s_carrname;
flight_count : abap.int4;
}
implemented by method zcl_my_amdp=>get_data;
AMDP 实现:
METHOD get_data
BY DATABASE FUNCTION
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING zcarrier_ve zflight_ve.
RETURN SELECT c.carrier_id,
c.carrier_name,
COUNT(*) AS flight_count
FROM zcarrier_ve AS c
INNER JOIN zflight_ve AS f
ON c.carrier_id = f.carrier_id
GROUP BY c.carrier_id, c.carrier_name;
ENDMETHOD.
AMDP 客户端安全性(ABAP Cloud)
| 附加项 | 使用场景 |
|---|---|
CDS SESSION CLIENT DEPENDENT | 使用依赖客户端的 CDS 视图(最常见) |
CLIENT INDEPENDENT | 仅使用与客户端无关的对象 |
AMDP OPTIONS READ-ONLY | ABAP for Cloud Development 中的必需项 |
输出格式
在解答 ABAP SQL 或 AMDP 相关问题时,按以下结构组织回复:
## ABAP SQL / AMDP Guidance
### Query
[The ABAP SQL statement or AMDP implementation]
### Explanation
[Key features used and why]
### Performance Notes
[Optimization considerations if relevant]
参考资料
- ABAP SQL 速查表:https://github.com/SAP-samples/abap-cheat-sheets
- AMDP 速查表:https://github.com/SAP-samples/abap-cheat-sheets/blob/main/12_AMDP.md
- ABAP SQL 参考:https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql.htm
SQL 和 AMDP 的 Clean Core 级别说明
| 场景 | 级别 | 说明 |
|---|---|---|
从已发布的 CDS 视图(I_*)中执行 SELECT | A | 目标状态 |
从自己的自定义表中执行 SELECT | A | 在同一软件组件内允许 |
从经典(指定的)SAP CDS 视图中执行 SELECT | B | 在经典 ABAP 开发中可以接受 |
| 直接从 SAP 数据库表中读取 | C | ATC 优先级 2 —— 改用已发布的 CDS 视图 |
| 直接向 SAP 数据库表中写入 | D | ATC 优先级 1 —— 使用已发布或经典 API |
EXEC SQL(原生 SQL) | D | 严重语句 —— 使用 ABAP SQL 或 AMDP |
| 数据库提示 | D | 严重语句 |
| 基于已发布 CDS 视图的 AMDP | A | 将 USING 限制为已发布的实体 |
| 基于 SAP 表的 AMDP | C/D | 读取 → C,写入 → D |
| 基于已发布实体的 AMDP CDS 表函数 | A | 有效的 A 级下推技术 |
性能优化:调整旧代码时,使用 SQL Monitor 检测优化候选项,然后通过 CDS、AMDP 和 ABAP SQL 执行代码下推,而不是直接使用原生 SQL 或数据库提示。
相关技能
- cds-view-entities:用于创建可与 ABAP SQL 配合使用的 CDS 数据模型
- abap-cloud:用于了解 Clean Core 级别和 SQL 相关限制
- rap:用于了解使用 CDS 视图的 RAP 数据模型
- abap-cloud-migration:用于在优化期间替换直接表访问和
EXEC SQL - atc-cloudification:用于配置
SYCM_USAGE_OF_APIS和CI_CRITICAL_STATEMENTS
评论
支持 Markdown