ABAP基础语法:变量、系统变量、数据类型与结构体变量详解


文章封面

ABAP基础语法:变量、系统变量、数据类型与结构体变量详解

一、教程概述

ABAP 开发中最基础、也最重要的内容,就是理解变量、系统变量、数据类型和结构体变量。无论是编写报表、ALV、接口、BAPI 调用,还是做增强开发,这些概念都会反复出现。

本文将从实际开发角度介绍:

  • ABAP 变量是什么
  • ABAP 变量如何声明和赋值
  • 常用 ABAP 系统变量有哪些
  • ABAP 常见数据类型
  • ABAP 结构体变量如何定义和使用
  • 每种写法的典型使用场景

二、什么是 ABAP 变量

变量是程序运行过程中用来保存数据的对象。

例如:

DATA lv_name TYPE string.
lv_name = '张三'.

这里:

  • DATA 表示声明变量
  • lv_name 是变量名
  • TYPE string 表示变量类型是字符串
  • '张三' 是赋给变量的值

在 ABAP 开发中,变量通常用于保存用户输入、数据库查询结果、中间计算结果、BAPI 返回消息、ALV 输出内容、接口请求和响应数据。

三、ABAP 变量命名习惯

虽然 ABAP 不强制要求变量前缀,但实际项目中通常会使用命名规范。

前缀含义示例
lv_Local Variable,普通变量lv_name
ls_Local Structure,结构体变量ls_customer
lt_Local Table,内表变量lt_customer
lr_Reference,引用变量lr_data
lo_Object,对象变量lo_alv
gv_Global Variable,全局变量gv_count
gs_Global Structure,全局结构gs_header
gt_Global Table,全局内表gt_item

示例:

DATA lv_count TYPE i.
DATA lv_name  TYPE string.
DATA ls_mara  TYPE mara.
DATA lt_mara  TYPE STANDARD TABLE OF mara.

良好的命名规范可以让代码更容易阅读,也能帮助开发者快速判断变量的用途和数据形态。

四、ABAP 变量声明方式

1. 使用 DATA 声明变量

DATA lv_name TYPE string.
DATA lv_age  TYPE i.

这是最常见的变量声明方式,适合定义程序中的普通变量。

业务示例:

DATA lv_total TYPE p LENGTH 15 DECIMALS 2.
DATA lv_msg   TYPE string.

lv_total 可以用于保存金额合计,lv_msg 可以用于保存处理消息。

2. 声明变量并赋初始值

DATA lv_name TYPE string VALUE '张三'.
DATA lv_age  TYPE i VALUE 20.

这种写法适合程序开始时就有默认值的变量,例如默认状态、默认语言、默认页大小等。

3. 使用 CONSTANTS 定义常量

CONSTANTS lc_status_success TYPE c LENGTH 1 VALUE 'S'.
CONSTANTS lc_status_error   TYPE c LENGTH 1 VALUE 'E'.

常量声明后不应该再被修改。它适合保存状态值、固定代码、默认配置等。

使用示例:

IF lv_type = lc_status_success.
  WRITE '处理成功'.
ENDIF.

4. 使用内联声明

现代 ABAP 支持内联声明,可以在使用变量的位置直接声明变量。

DATA(lv_name) = '张三'.
DATA(lv_count) = 100.

数据库查询时也很常见:

SELECT SINGLE matnr, mtart
  FROM mara
  INTO @DATA(ls_mara)
  WHERE matnr = @lv_matnr.

循环时也可以这样写:

LOOP AT lt_mara INTO DATA(ls_mara).
  WRITE: / ls_mara-matnr, ls_mara-mtart.
ENDLOOP.

内联声明适合临时变量、SELECT 查询结果、LOOP 循环变量和方法返回值接收。

五、什么是 ABAP 系统变量

ABAP 系统变量一般以 sy- 开头,由 SAP 系统自动维护。

系统变量用于表示当前运行环境、执行结果、用户信息、日期时间、循环状态等。开发中经常会用系统变量判断程序逻辑是否继续执行。

六、常用 ABAP 系统变量

1. sy-datum:当前日期

DATA lv_date TYPE d.
lv_date = sy-datum.

sy-datum 的格式是 YYYYMMDD,例如 20260803

常见使用场景:

  • 创建日期默认值
  • 过账日期默认值
  • 查询当天数据
  • 记录日志日期

示例:

WRITE: / '当前日期:', sy-datum.

2. sy-uzeit:当前时间

DATA lv_time TYPE t.
lv_time = sy-uzeit.

sy-uzeit 的格式是 HHMMSS

常见使用场景:

  • 记录操作时间
  • 生成日志
  • 统计程序执行时间

3. sy-uname:当前登录用户

WRITE: / '当前用户:', sy-uname.

常见使用场景:

  • 记录创建人
  • 权限判断
  • 日志追踪
  • 自动填充操作用户

例如:

ls_log-created_by = sy-uname.

4. sy-mandt:当前客户端

WRITE: / '当前客户端:', sy-mandt.

SAP 系统通常存在多个 Client,sy-mandt 可以标识当前客户端。

常见使用场景:

  • 多客户端系统中区分数据环境
  • 日志记录
  • 调试数据来源

5. sy-langu:当前登录语言

WRITE: / '当前语言:', sy-langu.

常见使用场景:

  • 多语言文本读取
  • 消息语言判断
  • 描述文本查询

示例:

SELECT SINGLE maktx
  FROM makt
  INTO @DATA(lv_maktx)
  WHERE matnr = @lv_matnr
    AND spras = @sy-langu.

6. sy-subrc:上一条语句执行结果

sy-subrc 是 ABAP 中非常重要的系统变量,用来判断上一条语句是否执行成功。

含义
0成功
4未找到数据或条件不满足
其他根据具体语句含义不同而不同

示例:

SELECT SINGLE *
  FROM mara
  INTO @DATA(ls_mara)
  WHERE matnr = @lv_matnr.

IF sy-subrc = 0.
  WRITE '物料存在'.
ELSE.
  WRITE '物料不存在'.
ENDIF.

常见使用场景:

  • 判断 SELECT 是否查到数据
  • 判断 READ TABLE 是否读取成功
  • 判断 AUTHORITY-CHECK 是否通过
  • 判断函数或方法执行结果

7. sy-tabix:当前内表行号

LOOP AT lt_mara INTO DATA(ls_mara).
  WRITE: / '当前行号:', sy-tabix.
ENDLOOP.

sy-tabix 常用于标准表和排序表的循环处理中。对于哈希表,不应依赖 sy-tabix

常见使用场景:

  • LOOP 中获取当前行号
  • 修改内表指定行
  • 调试数据处理过程

8. sy-index:当前循环次数

DO 5 TIMES.
  WRITE: / '当前循环次数:', sy-index.
ENDDO.

常见使用场景:

  • DO 循环计数
  • WHILE 循环辅助判断
  • 生成序号

9. sy-tcode:当前事务码

WRITE: / '当前事务码:', sy-tcode.

常见使用场景:

  • 判断程序从哪个事务码进入
  • 不同事务码执行不同逻辑
  • 日志记录操作入口

10. sy-repid:当前程序名

WRITE: / '当前程序:', sy-repid.

常见使用场景:

  • 日志记录
  • 动态调用
  • ALV 标识当前报表

11. sy-dbcnt:数据库影响行数

UPDATE ztable
  SET status = 'S'
  WHERE flag = 'X'.

WRITE: / '更新行数:', sy-dbcnt.

常见使用场景:

  • 判断 UPDATE 修改了多少行
  • 判断 DELETE 删除了多少行
  • 记录数据库处理数量

12. 消息相关系统变量

系统变量含义
sy-msgid消息类
sy-msgno消息编号
sy-msgty消息类型
sy-msgv1消息变量 1
sy-msgv2消息变量 2
sy-msgv3消息变量 3
sy-msgv4消息变量 4

这些变量常用于捕获 BAPI 返回消息、记录错误日志、构造异常信息。

七、ABAP 常用数据类型

ABAP 数据类型可以分为基础类型、字符类型、数值类型、日期时间类型、引用类型、结构类型和内表类型。

理解数据类型的关键是:类型规定了变量可以保存什么样的数据,以及这个数据如何参与计算、比较、赋值和输出。

八、字符相关类型

1. C:固定长度字符

DATA lv_code TYPE c LENGTH 10.
lv_code = 'A001'.

C 类型是固定长度字符,不足长度时右侧补空格。

常见使用场景:

DATA lv_bukrs TYPE c LENGTH 4.  "公司代码
DATA lv_werks TYPE c LENGTH 4.  "工厂

实际项目中更推荐使用 DDIC 类型:

DATA lv_bukrs TYPE bukrs.
DATA lv_werks TYPE werks_d.

2. STRING:动态字符串

DATA lv_text TYPE string.
lv_text = '这是一段动态长度文本'.

STRING 长度可变,适合长文本和拼接消息。

示例:

DATA lv_message TYPE string.
lv_message = |物料 { lv_matnr } 不存在|.

常见使用场景:

  • 日志消息
  • 错误提示
  • 接口报文
  • 拼接文本

3. N:数字字符

DATA lv_posnr TYPE n LENGTH 6.
lv_posnr = '10'.

结果通常表现为:

000010

N 本质是字符,不是数学数值,通常用于编号字段。

常见使用场景:

  • 销售订单行项目号
  • 采购订单行项目号
  • 流水号
  • 编号字段

九、日期和时间类型

1. D:日期类型

DATA lv_date TYPE d.
lv_date = sy-datum.

格式为 YYYYMMDD

常见使用场景:创建日期、交货日期、凭证日期、过账日期。

2. T:时间类型

DATA lv_time TYPE t.
lv_time = sy-uzeit.

格式为 HHMMSS

常见使用场景:创建时间、日志时间、操作时间。

十、数值类型

1. I:整数

DATA lv_count TYPE i.
lv_count = 100.

常见使用场景:计数、循环次数、内表行数、数量统计。

示例:

DATA lv_lines TYPE i.
DESCRIBE TABLE lt_mara LINES lv_lines.

2. P:压缩数

DATA lv_amount TYPE p LENGTH 15 DECIMALS 2.
lv_amount = '1234.56'.

P 类型可以设置小数位,常用于金额、数量、单价、重量和税额。

业务开发中建议优先参考标准字段类型:

DATA lv_wrbtr TYPE bseg-wrbtr.
DATA lv_menge TYPE ekpo-menge.

这样可以避免长度、小数位不一致的问题。

3. F:浮点数

DATA lv_rate TYPE f.
lv_rate = '3.14159'.

F 适合浮点计算,但可能存在精度问题,不建议用于财务金额。

常见使用场景:科学计算、比例计算、非金额类小数计算。

4. DECFLOAT16 和 DECFLOAT34

DATA lv_value TYPE decfloat34.
lv_value = '123456.789'.

常见使用场景:高精度小数计算、汇率计算、复杂价格模拟、精度要求较高的业务场景。

十一、优先使用 DDIC 类型

在 SAP 项目中,强烈建议优先使用数据字典字段类型。

推荐:

DATA lv_matnr TYPE mara-matnr.
DATA lv_kunnr TYPE kna1-kunnr.
DATA lv_vbeln TYPE vbak-vbeln.

不推荐随意写成:

DATA lv_matnr TYPE c LENGTH 18.
DATA lv_kunnr TYPE c LENGTH 10.

因为 DDIC 字段已经维护好了字段长度、数据元素、域、小数位、转换出口和业务语义。使用 DDIC 类型可以减少错误,提高代码稳定性。

十二、什么是 ABAP 结构体变量

结构体变量用于保存一组相关字段。

普通变量保存一个值:

DATA lv_name TYPE string.

结构体变量保存一条完整业务记录:

TYPES: BEGIN OF ty_customer,
         kunnr TYPE kna1-kunnr,
         name1 TYPE kna1-name1,
         land1 TYPE kna1-land1,
         ort01 TYPE kna1-ort01,
       END OF ty_customer.

DATA ls_customer TYPE ty_customer.

这里:

  • ty_customer 是结构体类型
  • ls_customer 是结构体变量
  • kunnrname1land1ort01 是结构体字段

十三、结构体变量赋值

1. 逐字段赋值

ls_customer-kunnr = '10000001'.
ls_customer-name1 = '测试客户'.
ls_customer-land1 = 'CN'.
ls_customer-ort01 = 'Shanghai'.

这种写法最直观,适合字段较少、逻辑较清楚的场景。

2. 使用 VALUE 赋值

ls_customer = VALUE ty_customer(
  kunnr = '10000001'
  name1 = '测试客户'
  land1 = 'CN'
  ort01 = 'Shanghai'
).

这种写法更集中,适合构造临时结构和初始化结构变量。

3. 从数据库查询赋值

SELECT SINGLE kunnr, name1, land1, ort01
  FROM kna1
  INTO @ls_customer
  WHERE kunnr = @lv_kunnr.

更稳妥的写法是按字段名匹配:

SELECT SINGLE kunnr, name1, land1, ort01
  FROM kna1
  INTO CORRESPONDING FIELDS OF @ls_customer
  WHERE kunnr = @lv_kunnr.

十四、结构体变量的使用场景

结构体变量非常适合表示一条业务数据。

业务对象结构体字段示例
客户客户号、名称、国家、城市
物料物料号、物料类型、基本单位、物料组
销售订单订单号、客户、销售组织、订单日期
采购订单采购订单号、供应商、采购组织、公司代码
ALV 输出数据库字段、状态字段、消息字段
接口数据请求头、业务字段、返回状态

当一个对象有多个属性时,就应该优先考虑使用结构体,而不是定义很多零散变量。

十五、结构体变量与内表

结构体通常表示一行数据,内表表示多行数据。

TYPES: BEGIN OF ty_material,
         matnr TYPE mara-matnr,
         mtart TYPE mara-mtart,
         matkl TYPE mara-matkl,
         meins TYPE mara-meins,
       END OF ty_material.

DATA ls_material TYPE ty_material.
DATA lt_material TYPE STANDARD TABLE OF ty_material.

添加一行数据:

ls_material-matnr = '000000000000000001'.
ls_material-mtart = 'FERT'.
ls_material-matkl = '001'.
ls_material-meins = 'PC'.

APPEND ls_material TO lt_material.

现代写法:

APPEND VALUE ty_material(
  matnr = '000000000000000001'
  mtart = 'FERT'
  matkl = '001'
  meins = 'PC'
) TO lt_material.

查询多条数据:

SELECT matnr, mtart, matkl, meins
  FROM mara
  INTO TABLE @lt_material
  UP TO 100 ROWS.

十六、典型业务示例:ALV 输出结构

在报表开发中,经常需要定义一个 ALV 输出结构。

这个结构通常由两部分组成:

数据库字段 + 程序处理字段

示例:

TYPES: BEGIN OF ty_alv,
         matnr  TYPE mara-matnr,
         maktx  TYPE makt-maktx,
         mtart  TYPE mara-mtart,
         matkl  TYPE mara-matkl,
         status TYPE c LENGTH 10,
         msg    TYPE string,
       END OF ty_alv.

DATA lt_alv TYPE STANDARD TABLE OF ty_alv.
DATA ls_alv TYPE ty_alv.

查询物料数据:

SELECT a~matnr,
       b~maktx,
       a~mtart,
       a~matkl
  FROM mara AS a
  INNER JOIN makt AS b
    ON b~matnr = a~matnr
  INTO CORRESPONDING FIELDS OF TABLE @lt_alv
  UP TO 100 ROWS
  WHERE b~spras = @sy-langu.

处理状态字段:

LOOP AT lt_alv INTO ls_alv.

  IF ls_alv-mtart = 'FERT'.
    ls_alv-status = '成品'.
    ls_alv-msg    = '该物料是成品物料'.
  ELSE.
    ls_alv-status = '其他'.
    ls_alv-msg    = '该物料不是成品物料'.
  ENDIF.

  MODIFY lt_alv FROM ls_alv.

ENDLOOP.

更推荐的写法:

LOOP AT lt_alv ASSIGNING FIELD-SYMBOL(<ls_alv>).

  IF <ls_alv>-mtart = 'FERT'.
    <ls_alv>-status = '成品'.
    <ls_alv>-msg    = '该物料是成品物料'.
  ELSE.
    <ls_alv>-status = '其他'.
    <ls_alv>-msg    = '该物料不是成品物料'.
  ENDIF.

ENDLOOP.

ASSIGNING FIELD-SYMBOL 可以直接修改内表当前行,不需要再执行 MODIFY

十七、结构体之间的赋值

1. 相同结构直接赋值

DATA ls_customer2 TYPE ty_customer.
ls_customer2 = ls_customer.

2. 不同结构按相同字段名赋值

现代写法:

ls_target = CORRESPONDING #( ls_source ).

老写法:

MOVE-CORRESPONDING ls_source TO ls_target.

常见使用场景:

  • 数据库结构转 ALV 结构
  • 接口结构转业务结构
  • BAPI 返回结构转日志结构
  • 抬头结构转输出结构

示例:

DATA ls_mara TYPE mara.
DATA ls_alv  TYPE ty_alv.

ls_alv = CORRESPONDING #( ls_mara ).

十八、嵌套结构体

结构体中可以包含另一个结构体。

TYPES: BEGIN OF ty_address,
         country TYPE land1,
         city    TYPE string,
         street  TYPE string,
       END OF ty_address.

TYPES: BEGIN OF ty_customer_deep,
         kunnr   TYPE kna1-kunnr,
         name1   TYPE kna1-name1,
         address TYPE ty_address,
       END OF ty_customer_deep.

DATA ls_customer_deep TYPE ty_customer_deep.

赋值:

ls_customer_deep-kunnr = '10000001'.
ls_customer_deep-name1 = '测试客户'.
ls_customer_deep-address-country = 'CN'.
ls_customer_deep-address-city = 'Shanghai'.
ls_customer_deep-address-street = 'Nanjing Road'.

常见使用场景:

  • 接口 JSON 数据
  • OData 深层结构
  • RAP 实体扩展
  • 复杂业务对象建模

十九、变量、系统变量、类型、结构体的关系

可以这样理解:

数据类型:规定数据长什么样
变量:根据数据类型创建出来的具体数据对象
系统变量:SAP 系统自动维护的特殊变量
结构体变量:由多个字段组成的变量,表示一条业务记录
内表:由多条结构体记录组成的数据集合

完整示例:

DATA lv_matnr TYPE mara-matnr.      "普通变量
DATA ls_mara  TYPE mara.            "结构体变量
DATA lt_mara  TYPE TABLE OF mara.   "内表变量

lv_matnr = '000000000000000001'.

SELECT SINGLE *
  FROM mara
  INTO @ls_mara
  WHERE matnr = @lv_matnr.

IF sy-subrc = 0.
  WRITE: / '物料号:', ls_mara-matnr.
  WRITE: / '物料类型:', ls_mara-mtart.
ELSE.
  WRITE: / '物料不存在'.
ENDIF.

这个例子中:

  • lv_matnr 是普通变量
  • ls_mara 是结构体变量
  • lt_mara 是内表变量
  • mara-matnr 是 DDIC 类型
  • sy-subrc 是系统变量

二十、实际开发建议

1. 优先使用 DDIC 类型

推荐:

DATA lv_kunnr TYPE kna1-kunnr.
DATA lv_matnr TYPE mara-matnr.
DATA lv_vbeln TYPE vbak-vbeln.

不推荐:

DATA lv_kunnr TYPE c LENGTH 10.
DATA lv_matnr TYPE c LENGTH 18.

2. 金额和数量字段不要随便自定义

推荐参考标准字段:

DATA lv_amount TYPE bseg-wrbtr.
DATA lv_qty    TYPE ekpo-menge.

这样可以避免长度、小数位不一致的问题。

3. 查询数据库后及时判断 sy-subrc

SELECT SINGLE *
  FROM kna1
  INTO @DATA(ls_kna1)
  WHERE kunnr = @lv_kunnr.

IF sy-subrc <> 0.
  MESSAGE '客户不存在' TYPE 'E'.
ENDIF.

4. 修改内表时优先使用 Field Symbol

LOOP AT lt_alv ASSIGNING FIELD-SYMBOL(<ls_alv>).
  <ls_alv>-status = 'S'.
ENDLOOP.

它比 LOOP INTO + MODIFY 更简洁,也更适合直接修改当前行。

5. 结构体适合表达业务对象

如果一个对象有多个属性,就应该使用结构体。

TYPES: BEGIN OF ty_order,
         vbeln TYPE vbak-vbeln,
         kunnr TYPE vbak-kunnr,
         erdat TYPE vbak-erdat,
         netwr TYPE vbak-netwr,
       END OF ty_order.

这种方式比定义一堆零散变量更清晰。

二十一、总结

ABAP 开发中的数据建模可以概括为四层:

基础类型:保存单个值
变量:程序中实际使用的数据对象
结构体变量:保存一条业务记录
内表变量:保存多条业务记录

系统变量则是 ABAP 运行时自动提供的上下文信息,例如当前用户、当前日期、执行结果、当前行号等。

实际项目中最常见的写法是:

DATA lv_matnr TYPE mara-matnr.

TYPES: BEGIN OF ty_alv,
         matnr  TYPE mara-matnr,
         maktx  TYPE makt-maktx,
         mtart  TYPE mara-mtart,
         status TYPE c LENGTH 10,
         msg    TYPE string,
       END OF ty_alv.

DATA lt_alv TYPE STANDARD TABLE OF ty_alv.

SELECT a~matnr,
       b~maktx,
       a~mtart
  FROM mara AS a
  INNER JOIN makt AS b
    ON b~matnr = a~matnr
  INTO CORRESPONDING FIELDS OF TABLE @lt_alv
  WHERE b~spras = @sy-langu.

IF sy-subrc = 0.
  LOOP AT lt_alv ASSIGNING FIELD-SYMBOL(<ls_alv>).
    <ls_alv>-status = 'S'.
    <ls_alv>-msg    = '读取成功'.
  ENDLOOP.
ENDIF.

掌握变量、系统变量、数据类型和结构体变量,是学习 ABAP 报表、接口、增强、BAPI、ALV 和 RAP 开发的基础。

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
MCP自动发表文章
评论列表

发表评论

评论内容
昵称:
验证码:
验证码
关联文章

ABAP基础语法系统数据类型结构变量详解
SAP ABAP 数据类型和常量基础
ABAP 基础语法教程:运算、字符串、判断循环
ABAP 数据字典 DDIC 详解:从 Domain 到透明表、搜索帮助锁对象
66. SAP S/4HANA EWM 入门:仓库结构基础流程企业组织定义
C#的进化——C#发展史、C#1.0-10.0语法系统性梳理、C#JAVA的对比
SAP S/4HANA OMS2物料类型字段详解:每个字段的意义常用配置
.NET C#教程初级篇 1-1 基本数据类型及其存储方式
SAP S/4HANA MM:采购组织的3种类型——工厂级、跨工厂跨公司代码详解
SQL Server中常用全局变量介绍
SAP S/4HANA FICO模块培训 31 - 公司代码会计年度
SAP S/4HANA MM模块培训 08 - 过账期间字段状态
SAP S/4HANA MM模块培训 03 - 采购组织、采购组物料主数据基础配置
Linq to SQL语句基础讲解
在cshtml文件中使用预编译语法
SQL Server 数据库类型和.NET数据类型映射关系
SAP S/4HANA MM模块培训 04 - 物料主数据、物料类型MM01创建
SAP S/4HANA MM模块培训 37 - 移动类型:控制功能、分类、冲销定制
SAP PP PP-PI 详解:从一辆自行车到一批果汁
SAP S/4HANA MM模块培训 09 - 字段状态验证 CO 基础配置