定义字段符号
字段符号使用 FIELD-SYMBOLS 语句声明。字段符号的名称应括在带角括号(< 和 >)中。您可以使用 TYPE 引用或 LIKE 引用定义字段符号,就像定义其他数据对象一样。
你也可以通过 TYPE ANY 来定义通用字段符号。在定义通用.类型的字段符号时,只能将相同类型的数据对象分配给字段符号。如果您计划静态访问结构的组件,这将非常有用。
例如,如果要处理物料主数据 MARA 结构体的各个组件,那么就应该完全定义字段符号。如果不定义字段符号,编译器在编译代码时就无法知道它包含哪些字段:
DATA st_mara TYPE mara.
FIELD-SYMBOLS: <fs_mara> TYPE mara,
<fs_matnr> TYPE matnr.
ASSIGN st_mara TO <fs_mara>.
<fs_mara>-matnr = 'PL1000'.
ASSIGN st_mara-matnr TO <fs_matnr>.
如果打算使用字段符号动态指向任何字段或结构,可以使用 TYPE ANY 附加语句将字段符号定义为通用类型,如下所示。但是,对于泛型类型,只有在运行时才会知道其组件,因此无法静态地访问它们。
DATA st_mara TYPE mara.
FIELD-SYMBOLs: <fs_any> TYPE ANY.
ASSIGN st_mara TO <fs_any>.
* <fs_any>-matnr = 'PL1000'. " 此时使用这句会导致语法错误
ASSIGN st_mara-matnr TO <fs_any>.
也可以为字段符号指定内表。要指定内表,应将字段符号定义为 TABLE 。可以按照如下定义的方式字段符号:
FIELD-SYMBOLS <fs_mara> TYPE STANDARD TABLE OF mara.
您可以将其定义为任何类型的内表,就像数据对象一样。您还可以执行适用于内表的所有操作和语句。例如,如果使用带有字段符号的 LOOP 语句,语法检查程序就不会出错。
如果打算动态分配任何内表(行类型只有在运行时才知道),可以使用 ANY TABLE 语法将字段符号定义为通用表,如下所示:
FIELD_SYMBOLS <fs_table> TYPE ANY TABLE.
分配数据对象: ASSIGN
语法
ASSIGN 语句用于将数据对象分配给一个字段符号,语法如下:
ASSIGN data_obj TO <fs>.
静态赋值
赋值操作可以静态和动态两种方式进行。如果我们知道要赋值给字段符号的数据对象名称,就可以静态赋值该数据对象,语法如下:
DATA st_mara TYPE mara.
FIELD-SYMBOLS: <fs_mara> TYPE mara.
ASSIGN st_mara TO <fs_mara>.
动态赋值
有时,我们可能只在运行时才知道要动态分配的数据对象。例如,您正在一个表中维护一些更改历史记录,并在其中存储字段名及其新旧值。在你的程序中,你只想处理变化历史表中有记录的字段。
这时,我们就可以动态分配数据对象,语法如下:
ASSIGN (name) TO <fs>.
在这段代码,name 变量包含数据对象的名称。变量应置于括号 () 内。 下面显示了一个动态赋值示例。
DATA field_name TYPE string.
FIELD-SYMBOLS <fs_field> TYPE ANY.
SELECT SINGLE ... FROM ... INTO field_name WHERE ....
ASSIGN (field_name) TO <fs_field>.
在这里,存储在 FIELD_NAME 变量中的数据对象名称将被赋值给字段符号。如果赋值成功(即程序中存在具有该字段名称的数据对象),SY-SUBRC 系统字段将被设置为 0。
使用动态赋值时,重要的是在访问字段符号之前检查字段符号是否已赋值。尝试访问未分配的字段符号将导致运行时错误。
类属性动态赋值
你可以对类的属性使用动态赋值,如下所示:
ASSIGN oref->(attribute_name) TO <fs>.
在此赋值中,属性名称是动态派生的。如果访问的是静态属性,甚至可以动态访问类名,如下:
ASSIGN (class_name)=>(attribute_name) TO <fs>.
ASSIGN (class_name)=>attribute TO <fs>.
动态分配结构
上面代码的第一行动态地指定了类名和属性名,而第二行动态地指定了类名,静态地指定了属性名。 您还可以使用以下语法动态分配结构的组件:
ASSIGN com OF STRUCTURE struc TO <fs>.
通过该语句 ,struc 结构中的 comp 组件被分配给 <fs> 字段符号。如果 comp 数据对象被设置为 TYPE c 或者 TYPE string,那么 comp 字段的内容将被解释为组件名称。例如,下面的代码中,st_mara 结构的 matnr 字段将被赋值给字段符号:
DATA: st_mara TYPE mara,
l_field TYPE string VALUE 'MATNR'.
FIELD-SYMBOLS: <fs_any> TYEP ANY.
ASSIGN l_field OF STRUCTURE st_mara TO <fs_any>.
但是,如果 comp 数据对象的类型不同并且带有数字,那么系统将把它解释为字段位置,并将该字段赋值给字段符号。 例如,在下面的代码中,st_mara 结构的第三个字段 mtart 将被分配给字段符号,因为 l_field 数据对象包含值 3:
TYPES: BEGIN OF ty_mara,
matnr TYPE matnr,
ersda TYPE ersda,
mtart TYPE mtart,
END OF ty_mara.
DATA : st_mara TYPE ty_mara,
l_field TYPE n VALUE 3.
FIELD-SYMBOLS: <fs_any> TYPE any.
ASSIGN l_field OF STRUCTURE st_mara TO <fs_any>
工作区字段符号
在处理内表时,可以将字段符号用作工作区。在 LOOP 或 READ 语句中使用 ASSIGNING(分配)附加语句将内表记录分配给字段符号,如下所示:
READ TABLE itab ASSIGNING <fs>...
LOOP AT itab ASSIGNING <fs>..
ENDLOOP.
当使用 LOOP 或 READ 语句将内表记录分配给字段符号时,字段符号将直接指向所分配的表记录。例如,在下面的代码中,我们将内表 IT_MARA 的第一行分配给 <FS_ MARA> 字段符号。 赋值后,字段符号将指向内表的第一行,您可以使用字段符号直接更改该行中的任何字段:
TYPES: BEGIN OF ty_mara,
matnr TYPE matnr,
ersda TYPE ersda,
mtart TYPE mtart,
END OF ty_mara.
DATA : it_mara TYPE TABLE OF ty_mara.
FIELD-SYMBOLS: <fs_mara> LIKE LINE OF it_mara.
PARAMETERS p_matnr TYPE matnr.
SELECT matnr ersda mtart FROM mara INTO TABLE it_mara WHERE matnr EQ p_matnr.
READ TABLE it_mara ASSIGNING <fs_mara> INDEX 1.
IF <fs_mara> IS ASSIGNED.
<fs_mara>-mtart = 'ROH'.
ENDIF.
在本例中,<FS_MARA>-MTART = 'ROH' 语句将更改内表第一行 MTART 字段的值。与工作区不同,使用字段符号时,不需要使用 MODIFY 语句将工作区的内容复制到内表中。
检查一个字符字段是否分配
如果要在赋值后立即检查,可以检查 SY-SUBRC 字段,如下所示:
ASSIGN dobj TO <fs>.
IF sy-subrc IS INITIAL.
<fs> = 123.
ENDIF.
不过,在大多数情况下,您并不需要在赋值后立即访问字段符号,而可能需要在代码的稍后部分访问它。在这种情况下,检查 SY-SUBRC 系统字段并没有什么用处,因为 SY-SUBRC 会被许多语句更新,而且它总是包含更新它的最后一条语句的结果。
要在访问字段符号之前确定它已被赋值,可使用 IS ASSIGNED 语句,语法如下:
IF <fs> IS ASSIGNED.
ENDIF。
我们建议您在访问字段符号之前,始终检查该字段符号是否已分配。尝试访问未分配的字段符号将导致无法处理的异常。
取消分配一个字段符号: UNASSIGN
如果要删除字段符号的赋值,以确保没有数据对象赋值给它,请使用 UNASSIGN 语句,如下所示:
UNASSIGN <fs>.
取消赋值后,字段符号将被初始化,因此不会指向任何数据对象。除非有其他数据对象分配给字段符号,否则在取消分配后,不应访问该字段符号。
注意:使用 CLEAR 语句不会初始化字段符号,只会清除分配给字段符号的数据对象的内容。
Casting 类型转换
将数据对象分配给字段符号时,字段符号的类型应与数据对象兼容。不过,在将数据对象分配给字段符号时,可以对任何数据类型执行转换。
通过转换 Casting ,可以将特定数据类型视为另一种数据类型。这意味着,内存中的任何区域都可以被视为具有特定类型。例如,在将数据对象分配给字段符号时,可以通过执行转换操作将字符字段的值解释为日期字段。
CASTING 用于类型转换,如下代码:
ASSIGN dobj TO <fs> CASTING.
使用 CASTING 时,可以将不同类型的数据对象分配给字段符号。通过 Casting,可以将与字段符号不兼容的数据对象分配给字段符号。
如下显示的示例代码中,TYPE C 的字段被分配给 TYPE D 的字段符号。分配数据对象后,数据对象的内容将被解释为 TYPE D。
DATA text(8) TYPE c VALUE '20241129'.
FIELD_SYMBOLS <fs> TYPE sy-datum.
ASSIGN text TO <fs> CASTING.
WRITE <fs>.
转换可以隐式或显式执行。如果字段符号是通用类型或使用 ABAP 内置类型(c、n、p 或 x)之一进行泛型,则 CASTING 可与 ASSIGN 语句一起使用,该语句会执行隐式转换,将分配的内存转换为字段符号的类型。
如果字段符号是通用类型,则可以通过在 ASSIGN 语句中指定数据类型来执行显式转换,如下所示:
ASSIGN dobj TO <fs> CASTING [TYPE data_type|LIKE dobj].
在 CASTING 语句附加后,您可以指定数据类型或数据对象。转换将根据指定的类型进行。指定的类型应与字段符号的通用类型兼容,而不应对完全类型的字段符号执行显式类型。通过类型转换,可以对数据进行不同的解释。
在本文中,我们讨论了字段符号在动态编程中的使用。在下一篇文章中,我们将了解如何使用数据引用来指向内存中的数据对象。