It looks and behaves like a normal string, except in the database.

Character Data Types

ABAP has two data types for character data: CHAR and STRING. The difference between the two is that a CHAR type has a fixed length, whereas a STRING can be arbitrarily long (they also differ in how trailing whitespaces are handled and whether they can be used in screens, but those are not especially relevant for the topic at hand).

1
2
3
4
5
DATA lv_char TYPE c.                    " Char variable with a length of 1
DATA lv_char20 TYPE c LENGTH 20.        " Char variable with a length of 20
DATA lv_char20_old_syntax(20) TYPE c.   " Char variable with a length of 20

DATA lv_string TYPE string. " A string variable

Obviously it would inconvenient – not to mention, bug-ridden – to have to define the length of each variable explicitly each time they are needed. This is avoided with two types of entries in the ABAP Data Dictionary: Domains and Data Elements.

Domains

Domains define technical details like the data type, length of the data and case sensitivity. It is also possible to specify a conversion routine which converts values between display and in-memory representations.

MATNR Definition

Domains can also specify allowed values (or value ranges) explicitly or by referencing a table. These settings can then be used to generate drop-down lists and other UI elements.

MATNR Value Range

Note, however, that these “allowed values” are only enforced in selection screens and other GUI elements. It is perfectly possible to assign any random character string to a variable that is based on the MATNR Domain.

Data Elements

Domains cannot be used to declare variables. One or more Data Elements must be defined based on a Domain, and these Data Elements can then be used in ABAP.

1
DATA lv_material TYPE matnr. " References MATNR Data Element, not the Domain

Data Elements add additional semantic meaning to Domain values. Consider, for example, a Stock Transport Order (STO) (a transfer of material from one plant to another). In an STO, there are at least two plants, a supplying plant (RESWK) and a receiving plant (EWERK). Both values are plant identifiers, ie. from the same domain of allowed values, but the distinct Data Elements signify the different roles the plants play in a given document.

RESWK Data Element

EWERK Data Element

I think it’s pretty close to accurate to think of Domain as a typedef, and Data Elements as additional typedef based on the previous one. Obviously it’s not 1:1, since the allowed values, input/output conversions and descriptions are extras not available in C, but the basic picture holds.

1
2
3
4
5
6
typedef struct werks {
    char id[5];
} werks;

typedef struct werks reswk;
typedef struct werks ewerk;

CHAR, STRING and SSTRING Data Types

ABAP has a number of data types which can be used when defining Domains.

Data Types

Of interest to us are CHAR, SSTRING and STRING. See how those data types look in this database table? CHAR_FIELD and SSTRING_FIELD both have defined lengths, whereas the STRING_FIELD does not.

ZTABLE Database Table

And to stir things a little bit further, the following code executes without any of the assertions failing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
DATA(lv_string) = REDUCE string(
  INIT tmp = ||
  FOR len = 0 WHILE len < 26
  NEXT tmp = tmp && sy-abcde+len(1)
).


DATA(ls_ztable) = VALUE ztable(
  char_field    = lv_string
  sstring_field = lv_string
  string_field  = lv_string
).


" Contains the whole string
ASSERT ls_ztable-string_field = lv_string.

" Contains the whole string
ASSERT ls_ztable-sstring_field = lv_string.

" Only the first 10 characters fit in the text field
ASSERT ls_ztable-char_field = lv_string(10).

Why are both STRING_FIELD and SSTRING_FIELD equal to the string variable, which at 26 characters obviously exceeds the maximum length of the SSTRING_FIELD member, whereas the CHAR_FIELD is truncated to just the first 10 characters?

To complete the picture, here’s a slightly amended program and its aftermath:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
DATA(lv_string) = REDUCE string(
  INIT tmp = ||
  FOR len = 0 WHILE len < 26
  NEXT tmp = tmp && sy-abcde+len(1)
).


DATA(ls_ztable) = VALUE ztable(
  char_field    = lv_string
  sstring_field = lv_string
  string_field  = lv_string
).


" Contains the whole string
ASSERT ls_ztable-string_field = lv_string.

" Contains the whole string
ASSERT ls_ztable-sstring_field = lv_string.

" Only the first 10 characters fit in the text field
ASSERT ls_ztable-char_field = lv_string(10).


INSERT ztable FROM ls_ztable.
COMMIT WORK.

Short Dump

When we try to commit the value to database, the program crashes because “The length of a parameter (input/output) is invalid”. Checking the documentation for data types, we can find the following:

SSTRING Documentation

Ie. in memory an SSTRING is just a normal string, but when it is committed to the database, the length limit is enforced.

CHAR vs SSTRING

The documentation explicitly mentions as the rationale for SSTRING that it allows a string type to be used in a database as if it were a char. But since this means that the field cannot be arbitrarily long – the main advantage of a string over a char –, it would seem to me that it is easier and safer to just use a char. This eliminates all cases where the contents of a field could ever exceed the allowed length. The main downside that comes to mind is that this might mean that the value is silent truncated, ie. possibly corrupted; but since an explicit length check and the associated exception handling would need to occur at some point with an SSTRING, guarding against silent truncation doesn’t seem like something that can be avoided in either case.

Ie. don’t use SSTRING, CHAR will do equally nicely.