-
Notifications
You must be signed in to change notification settings - Fork 289
/
zcl_demo_abap_internal_tables.clas.abap
3341 lines (2542 loc) · 125 KB
/
zcl_demo_abap_internal_tables.clas.abap
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
"! <p class="shorttext"><strong>Dynamic programming</strong><br/>ABAP cheat sheet example class</p>
"!
"! <p>The example class demonstrates working with internal tables.<br/>
"! Choose F9 in ADT to run the class.</p>
"!
"! <h2>Note</h2>
"! <p>Find information on <strong>getting started with the example class</strong> and the
"! <strong>disclaimer</strong> in the ABAP Doc comment of class {@link zcl_demo_abap_aux}.</p>
CLASS zcl_demo_abap_internal_tables DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
CLASS-METHODS class_constructor.
PROTECTED SECTION.
PRIVATE SECTION.
CLASS-METHODS fill_dbtabs.
ENDCLASS.
CLASS zcl_demo_abap_internal_tables IMPLEMENTATION.
METHOD class_constructor.
zcl_demo_abap_aux=>fill_dbtabs( ).
fill_dbtabs( ).
ENDMETHOD.
METHOD fill_dbtabs.
"Initializing and populating database tables to have data to work with
DELETE FROM zdemo_abap_tab1.
DELETE FROM zdemo_abap_tab2.
MODIFY zdemo_abap_tab1 FROM TABLE @( VALUE #(
( key_field = 100 char1 = 'aaa' char2 = 'bbb' num1 = 1 num2 = 2 )
( key_field = 200 char1 = 'ccc' char2 = 'ddd' num1 = 3 num2 = 4 )
( key_field = 300 char1 = 'eee' char2 = 'fff' num1 = 5 num2 = 6 )
( key_field = 400 char1 = 'ggg' char2 = 'hhh' num1 = 7 num2 = 8 ) ) ).
MODIFY zdemo_abap_tab2 FROM TABLE @( VALUE #(
( key_field = 500 char1 = 'iii' num1 = 10 numlong = 1000 )
( key_field = 600 char1 = 'kkk' num1 = 12 numlong = 2000 )
( key_field = 700 char1 = 'mmm' num1 = 14 numlong = 3000 )
( key_field = 800 char1 = 'ooo' num1 = 15 numlong = 4000 ) ) ).
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
out->write( |ABAP cheat sheet example: Internal tables\n\n| ).
out->write( |1) Creating Internal Tables By Inline Declaration\n\n| ).
"Table declared inline in the context of an assignment
"The examples show the copying of a table including the content
"on the fly and creating the table in one step. The data type of the
"declared variable is determined by the right side.
"The table type here is a predefined and globally available table type.
DATA string_tab TYPE string_table.
DATA(it_1) = string_tab.
DATA(it_2) = it_1.
"Using FINAL for creating immutable variables
FINAL(it_3) = it_1.
"For example, it is not possible to modify such a table in the following position.
"APPEND INITIAL LINE TO it_3.
"As shown below and in other cheat sheets, constructor operators
"are handy when creating internal tables in place. The following
"examples uses the VALUE operator and an internal table type.
DATA(it_4) = VALUE string_table( ( `aaa` )
( `bbb` ) ).
"Not providing any table lines means the table is initial
"and has the same effect as the declaration of it6.
DATA(it_5) = VALUE string_table( ).
DATA it_6 TYPE string_table.
"Excursion
"Table declared inline in the context of a SELECT statement;
"a prior extra declaration of an internal table is not needed.
SELECT * FROM zdemo_abap_fli INTO TABLE @DATA(it_7).
"Instead of
DATA it_8 TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY.
SELECT * FROM zdemo_abap_fli INTO TABLE @it_8.
"Using FINAL
SELECT * FROM zdemo_abap_fli INTO TABLE @FINAL(it_9).
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `2) Populating internal tables by adding a line (structure) using APPEND ... TO/INSERT ... INTO` ) ).
TYPES: BEGIN OF st_a,
num TYPE i,
str TYPE string,
char TYPE c LENGTH 2,
END OF st_a,
ty_tab_a TYPE TABLE OF st_a WITH EMPTY KEY.
DATA it_a TYPE ty_tab_a.
"Adding a line created inline
APPEND VALUE #( num = 1 str = `A` char = 'bb' ) TO it_a.
INSERT VALUE #( num = 2 str = `C` char = 'dd' ) INTO TABLE it_a.
"Adding an existing line
DATA(struc_a) = VALUE st_a( num = 3 str = `E` char = 'ff' ).
"Structure whose components are assigned individually using the
"structure component selector
DATA struc_b TYPE st_a.
struc_b-num = 4.
struc_b-str = `G`.
struc_b-char = 'hh'.
APPEND struc_a TO it_a.
INSERT struc_b INTO TABLE it_a.
out->write( data = it_a name = `it_a` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `3) Adding an initial line` ) ).
APPEND INITIAL LINE TO it_a.
INSERT INITIAL LINE INTO TABLE it_a.
out->write( data = it_a name = `it_a` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `4) Adding a line and assigning the added line to a field symbol or data reference variable` ) ).
"Creating field symbol inline
APPEND VALUE st_a( num = 5 str = `I` char = 'jj' ) TO it_a ASSIGNING FIELD-SYMBOL(<fs_a>).
"Addressing individual components
ASSERT <fs_a>-num = 5.
<fs_a>-num = 123.
FIELD-SYMBOLS <fs_b> TYPE st_a.
DATA(struc_c) = VALUE st_a( num = 6 ).
INSERT struc_c INTO TABLE it_a ASSIGNING <fs_b>.
<fs_b>-str = `K`.
"Adding an initial line
"The examples use data reference variables.
"Using inline declaration
APPEND INITIAL LINE TO it_a REFERENCE INTO DATA(dref_a).
dref_a->num = 7.
DATA dref_b TYPE REF TO st_a.
INSERT INITIAL LINE INTO TABLE it_a REFERENCE INTO dref_b.
dref_b->num = 8.
DO 3 TIMES.
APPEND INITIAL LINE TO it_a REFERENCE INTO dref_b.
dref_b->* = VALUE #( num = sy-index str = sy-index char = sy-index ).
ENDDO.
out->write( data = it_a name = `it_a` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `5) Adding all lines from another internal table (LINES OF addition)` ) ).
"Adding lines to one internal table that are all added to
"another one
DATA it_b TYPE ty_tab_a.
INSERT VALUE #( num = 99 str = `L` char = 'mm' ) INTO TABLE it_b.
INSERT VALUE #( num = 100 str = `N` char = 'oo' ) INTO TABLE it_b.
APPEND LINES OF it_b TO it_a.
INSERT LINES OF it_b INTO TABLE it_a.
out->write( data = it_a name = `it_a` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `6) Adding multiple lines from another internal table with a specified index range` ) ).
APPEND LINES OF it_a FROM 5 TO 7 TO it_b.
APPEND LINES OF it_a FROM 12 TO it_b. "further lines up to the last line
APPEND LINES OF it_a TO 3 TO it_b. "all lines from the start up to the specified index
INSERT LINES OF it_a FROM 8 TO 10 INTO TABLE it_b.
out->write( data = it_b name = `it_b` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `7) Inserting one line or multiple lines from another internal table at a specific position (INDEX addition)` ) ).
"To be used for index tables.
INSERT VALUE #( num = 9 str = `P` char = 'qq' ) INTO it_b INDEX 2.
INSERT LINES OF VALUE ty_tab_a( ( num = 10 str = `R` ) ( num = 11 str = `S` ) ) INTO it_b INDEX 5.
"FROM and TO can also be used
INSERT LINES OF it_a FROM 1 TO 3 INTO it_b INDEX 1.
out->write( data = it_b name = `it_b` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `8) Adding lines using the VALUE operator` ) ).
DATA(struc_d) = VALUE st_a( num = 11 str = `T` char = 'uu' ).
DATA it_c TYPE ty_tab_a.
"Populating an existing internal table by assigning an internal table that is constructed inline
"Adding an existing line and a line created inline
it_c = VALUE #( ( struc_d )
( num = 11 str = `V` char = 'ww' ) ).
out->write( data = it_c name = `it_c` ).
out->write( |\n| ).
"Creating an internal table by inline declaration and adding lines with VALUE
DATA(it_d) = VALUE ty_tab_a( ( num = 12 str = `X` char = 'yy' )
( num = 13 str = `Z` char = 'aa' )
( struc_d ) ).
out->write( data = it_d name = `it_d` ).
out->write( |\n| ).
"******* BASE addition *******
"Adding new lines without deleting existing content
it_d = VALUE #( BASE it_d ( num = 14 str = `B` char = 'cc' )
( num = 15 str = `D` char = 'ee' ) ).
out->write( data = it_d name = `it_d` ).
out->write( |\n| ).
"******* LINES OF addition *******
"Adding lines of other tables
it_d = VALUE #( ( LINES OF it_c ) ). "No BASE addition, existing content is deleted
it_c = VALUE #( BASE it_c ( num = 16 str = `F` char = 'gg' )
( LINES OF it_d ) ).
out->write( data = it_d name = `it_d` ).
out->write( |\n| ).
out->write( data = it_c name = `it_c` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `9) CORRESPONDING operator / MOVE-CORRESPONDING statements` ) ).
"Creating and populating demo internal tables
TYPES: BEGIN OF st_b,
num TYPE i,
char TYPE c LENGTH 2,
comp_a TYPE string,
END OF st_b,
ty_tab_b TYPE TABLE OF st_b WITH EMPTY KEY,
BEGIN OF st_c,
num TYPE i,
char TYPE c LENGTH 2,
comp_b TYPE string,
END OF st_c,
ty_tab_c TYPE TABLE OF st_c WITH EMPTY KEY.
DATA(it_e_original) = VALUE ty_tab_b( ( num = 1 char = 'aa' comp_a = `B` )
( num = 2 char = 'cc' comp_a = `D` ) ).
DATA(it_f_original) = VALUE ty_tab_c( ( num = 3 char = 'ee' comp_b = `F` )
( num = 4 char = 'gg' comp_b = `H` ) ).
DATA(it_e) = it_e_original.
DATA(it_f) = it_f_original.
"Copying the content of another internal table respecting identically
"named components
"it_f -> it_e
it_e = CORRESPONDING #( it_f ).
out->write( `CORRESPONDING` ).
out->write( data = it_e name = `it_e` ).
out->write( |\n| ).
"it_e -> it_f
it_e = it_e_original.
MOVE-CORRESPONDING it_e TO it_f.
out->write( `MOVE-CORRESPONDING` ).
out->write( data = it_f name = `it_f` ).
out->write( |\n| ).
"******* BASE addition / KEEPING TARGET LINES addition *******
"Copying content and retaining existing content
it_e = it_e_original.
it_f = it_f_original.
out->write( `CORRESPONDING ... BASE ...` ).
it_e = CORRESPONDING #( BASE ( it_e ) it_f ).
out->write( data = it_e name = `it_e` ).
out->write( |\n| ).
it_e = it_e_original.
it_f = it_f_original.
out->write( `MOVE-CORRESPONDING ... KEEPING TARGET LINES ...` ).
MOVE-CORRESPONDING it_e TO it_f KEEPING TARGET LINES.
out->write( data = it_f name = `it_f` ).
out->write( |\n| ).
"******* MAPPING addition *******
"Assigning components using mapping relationships
it_e = it_e_original.
it_f = it_f_original.
out->write( `CORRESPONDING ... MAPPING ...` ).
it_e = CORRESPONDING #( it_f MAPPING comp_a = comp_b ).
out->write( data = it_e name = `it_e` ).
out->write( |\n| ).
out->write( `CORRESPONDING ... BASE ... MAPPING ...` ).
it_e = it_e_original.
it_f = CORRESPONDING #( BASE ( it_f ) it_e MAPPING comp_b = comp_a ). "Retaining content with BASE
out->write( data = it_f name = `it_f` ).
out->write( |\n| ).
"******* EXCEPT addition *******
"Excluding components from the assignment
it_e = it_e_original.
it_f = it_f_original.
out->write( `CORRESPONDING ... EXCEPT ...` ).
it_e = CORRESPONDING #( it_f EXCEPT char ).
out->write( data = it_e name = `it_e` ).
out->write( |\n| ).
it_e = it_e_original.
"EXCEPT * means that all components remain initial not specified
"for mapping
out->write( `CORRESPONDING ... MAPPING ... EXCEPT ...` ).
it_f = CORRESPONDING #( it_e MAPPING comp_b = comp_a EXCEPT * ). "Mapping components
out->write( data = it_f name = `it_f` ).
out->write( |\n| ).
"******* DISCARDING DUPLICATES addition *******
"Preventing runtime errors when duplicate lines are assigned
it_e = VALUE #( ( num = 1 char = 'aa' comp_a = `B` )
( num = 1 char = 'cc' comp_a = `D` ) ).
DATA it_g TYPE SORTED TABLE OF st_b WITH UNIQUE KEY num.
"The statement commented out raises the runtime error ITAB_DUPLICATE_KEY.
"it_g = CORRESPONDING #( it_e ).
out->write( `CORRESPONDING ... DISCARDING DUPLICATES ...` ).
it_g = CORRESPONDING #( it_e DISCARDING DUPLICATES ).
out->write( data = it_g name = `it_g` ).
out->write( |\n| ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `10) DEEP addition to the CORRESPONDING operator / EXPANDING NESTED TABLES addition to MOVE-CORRESPONDING statements` ) ).
"Handling deep components such as nested internal tables
"Creating and populating demo internal tables
TYPES: BEGIN OF st_d,
char_a TYPE c LENGTH 2,
char_b TYPE c LENGTH 2,
END OF st_d,
BEGIN OF st_e,
char_b TYPE c LENGTH 2,
char_c TYPE c LENGTH 2,
END OF st_e,
BEGIN OF st_f,
comp1 TYPE c LENGTH 2,
comp2 TYPE c LENGTH 2,
comp3 TYPE TABLE OF st_d WITH EMPTY KEY,
END OF st_f,
BEGIN OF st_g,
comp2 TYPE c LENGTH 2,
comp3 TYPE TABLE OF st_e WITH EMPTY KEY,
comp4 TYPE c LENGTH 2,
END OF st_g,
ty_tab_d TYPE TABLE OF st_f WITH EMPTY KEY,
ty_tab_e TYPE TABLE OF st_g WITH EMPTY KEY.
DATA(it_h_original) = VALUE ty_tab_d(
( comp1 = 'a1' comp2 = 'a2' comp3 = VALUE #( ( char_a = 'a3' char_b = 'a4' ) ( char_a = 'a5' char_b = 'a6' ) ) )
( comp1 = 'b1' comp2 = 'b2' comp3 = VALUE #( ( char_a = 'b3' char_b = 'b4' ) ( char_a = 'b5' char_b = 'b6' ) ) ) ).
DATA(it_i_original) = VALUE ty_tab_e(
( comp2 = 'c1' comp3 = VALUE #( ( char_b = 'c2' char_c = 'c3' ) ( char_b = 'c4' char_c = 'c5' ) ) comp4 = 'c6' )
( comp2 = 'd1' comp3 = VALUE #( ( char_b = 'd2' char_c = 'd3' ) ( char_b = 'd4' char_c = 'd5' ) ) comp4 = 'd6' ) ).
DATA(it_h) = it_h_original.
DATA(it_i) = it_i_original.
"Compare the output of the examples
out->write( `******* CORRESPONDING *******` ).
"Note: The following example uses just CORRESPONDING. The outcome of the assignment
"is a different one compared to using DEEP. Refer to the ABAP Keyword Documentation
"for more details.
it_h = CORRESPONDING #( it_i ).
out->write( it_h ).
out->write( `******* CORRESPONDING ... DEEP *******` ).
it_h = CORRESPONDING #( DEEP it_i ).
out->write( it_h ).
out->write( `******* CORRESPONDING ... DEEP BASE *******` ).
it_h = it_h_original.
it_h = CORRESPONDING #( DEEP BASE ( it_h ) it_i ).
out->write( it_h ).
out->write( `******* MOVE-CORRESPONDING ... EXPANDING NESTED TABLES *******` ).
it_h = it_h_original.
MOVE-CORRESPONDING it_i TO it_h EXPANDING NESTED TABLES.
out->write( it_h ).
out->write( `******* MOVE-CORRESPONDING ... EXPANDING NESTED TABLES KEEPING TARGET LINES *******` ).
it_h = it_h_original.
MOVE-CORRESPONDING it_i TO it_h EXPANDING NESTED TABLES KEEPING TARGET LINES.
out->write( it_h ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `11) CORRESPONDING with lookup table` ) ).
"The following examples construct an internal tables by joining an internal table
"and a lookup table and comparing their components.
TYPES:
BEGIN OF s_lk1,
character TYPE c LENGTH 1,
text TYPE string,
END OF s_lk1,
it_type TYPE STANDARD TABLE OF s_lk1 WITH EMPTY KEY,
lookup_tab_type TYPE HASHED TABLE OF s_lk1 WITH UNIQUE KEY character.
DATA(it_lk1) = VALUE it_type( ( character = 'a' ) ( character = 'b' ) ( character = 'c' ) ( character = 'd' )
( character = 'e' ) ( character = 'f' ) ).
DATA(it_lk1_copy) = it_lk1.
DATA(lookup_tab) = VALUE lookup_tab_type( ( character = 'a' text = `lorem` )
( character = 'c' text = `ipsum` )
( character = 'e' text = `dolor` )
( character = 'f' text = `sit` ) ).
"In the following example assignment, the internal table used for the comparison
"is also the target table.
it_lk1 = CORRESPONDING #( it_lk1 FROM lookup_tab USING character = character ).
out->write( data = it_lk1 name = `it_lk1` ).
out->write( |\n| ).
"In the following example, the internal table used for the comparison
"is not the target table. Instead, a new table is created inline.
"The pragma suppresses a syntax warning.
DATA(it_lk2) = CORRESPONDING it_type( it_lk1_copy FROM lookup_tab USING character = character ) ##operator.
ASSERT it_lk2 = it_lk1.
out->write( data = it_lk2 name = `it_lk2` ).
out->write( |\n| ).
"Example assignments to demonstrate the KEY and MAPPING additions
TYPES:
BEGIN OF s_lk2,
a TYPE string,
b TYPE string,
c TYPE string,
d TYPE string,
e TYPE string,
f TYPE string,
END OF s_lk2,
BEGIN OF s_lk3,
a TYPE string,
b TYPE string,
c TYPE string,
d TYPE string,
e TYPE string,
g TYPE string,
END OF s_lk3,
BEGIN OF s_lk4,
h TYPE string,
i TYPE string,
j TYPE string,
k TYPE string,
l TYPE string,
m TYPE string,
END OF s_lk4.
DATA:
it_lk3 TYPE STANDARD TABLE OF s_lk2,
it_lk4 TYPE STANDARD TABLE OF s_lk2,
it_lk5 TYPE STANDARD TABLE OF s_lk2,
lookup_table TYPE STANDARD TABLE OF s_lk3 WITH NON-UNIQUE SORTED KEY sk COMPONENTS c d,
it_lk6 TYPE STANDARD TABLE OF s_lk4.
it_lk3 = VALUE #( ( a = `1a` b = `1b`
c = `---` d = `---`
e = `---` f = `---` )
( a = `2a` b = `2b`
c = `---` d = `---`
e = `---` f = `---` )
( a = `3a` b = `3b`
c = `---` d = `---`
e = `---` f = `---` ) ).
it_lk4 = it_lk3.
it_lk5 = it_lk3.
lookup_table = VALUE #( ( a = `4a` b = `4b`
c = `1a` d = `1b`
e = `5a` g = `5b` )
( a = `6a` b = `6b`
c = `3a` d = `3b`
e = `7a` g = `7b` ) ).
"Notes on the example assignment:
"- Internal table used for the comparison is also the target table
"- The lookup table specifies a sorted secondary table key.
"- The key is used after the USING KEY addition.
"- All key components must be specified.
"- Regarding the result:
" - Only the first and third lines are found in the lookup table.
" - Therefore, the values of the identically named components in it3
" are assigned (which is only one component in the example).
" - The assignment excludes the components c and d of the lookup table,
" although there are identically named components in it3. The components
" used in the condition specification are ignored. The other components
" retain their original values.
" - In the lookup table, no line is available with the values a = `2a` b = `2b`.
" Therefore, the result does not include values from the lookup table. The
" original component values of the line in it3 are used for the result.
it_lk3 = CORRESPONDING #( it_lk3 FROM lookup_table USING KEY sk c = a d = b ).
out->write( data = it_lk3 name = `it_lk3` ).
out->write( |\n| ).
"Notes on the example assignment:
"- See above. Here, the MAPPING addition is included. It is used to specify
" mapping relationships for the assignments. The example specifies a mapping
" relationship for all available components in the demo tables. In doing so,
" the default mapping is overridden, and, all previously ignored components
" are not ignored anymore.
"- As a consequence, all component values in the first and third lines are
" are affected and assigned values.
"- As above, the second line retains the original values of it4 as there is
" no line found in the lookup table.
it_lk4 = CORRESPONDING #( it_lk4 FROM lookup_table USING KEY sk c = a d = b MAPPING a = a b = b c = c d = d f = g ).
out->write( data = it_lk4 name = `it_lk4` ).
out->write( |\n| ).
"Notes on the example assignment:
"- The target table does not have the same type as it5. But, despite having differently
" named components, the types are compatible, and an assignment can be performed.
"- As not the same internal table is used for the search in the CORRESPONDING expression and
" the target, a syntax warning would occur (a temporary copy of it5 must be created) if not
" hidden by the pragma.
it_lk6 = CORRESPONDING #( it_lk5 FROM lookup_table USING KEY sk c = a d = b ) ##operator.
out->write( data = it_lk6 name = `it_lk6` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `12) Creating anonymous internal tables with the NEW operator` ) ).
TYPES: BEGIN OF s,
a TYPE c LENGTH 3,
b TYPE i,
END OF s,
tab_type TYPE TABLE OF s WITH EMPTY KEY.
"Creating and populating an anonymous data object
DATA(dref_tab) = NEW tab_type( ( a = 'aaa' b = 1 )
( a = 'bbb' b = 2 ) ).
"Access by derefencing
DATA(copy_deref_itab) = dref_tab->*.
DATA(read_line) = dref_tab->*[ 2 ].
DATA(read_comp) = dref_tab->*[ 1 ]-a.
dref_tab->*[ 1 ]-a = 'zzz'.
ASSERT dref_tab->*[ 1 ]-a = 'zzz'.
INSERT VALUE s( a = 'yyy' b = 3 ) INTO TABLE dref_tab->*.
out->write( data = dref_tab->* name = `dref_tab->*` ).
out->write( |\n| ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `13) FILTER: Filtering internal table by condition` ) ).
"This section covers multiple examples demonstrating the syntactical variety
"of the FILTER operator.
TYPES: BEGIN OF fi_str,
a TYPE i,
b TYPE c LENGTH 3,
c TYPE c LENGTH 3,
END OF fi_str.
"basic form, condition created with single values
"itab must have at least one sorted key or one hash key used for access.
"This variant of the filter operator is not possible for an internal table itab without a sorted key or hash key.
DATA fi_tab1 TYPE SORTED TABLE OF fi_str WITH NON-UNIQUE KEY a.
DATA fi_tab2 TYPE STANDARD TABLE OF fi_str WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS a.
DATA fi_tab3 TYPE HASHED TABLE OF fi_str WITH UNIQUE KEY a.
"Filling internal tables
fi_tab1 = VALUE #( ( a = 1 b = 'aaa' c = 'abc' )
( a = 2 b = 'bbb' c = 'def' )
( a = 3 b = 'ccc' c = 'hij' )
( a = 4 b = 'ddd' c = 'klm' )
( a = 5 b = 'eee' c = 'nop' ) ).
fi_tab2 = fi_tab1.
fi_tab3 = fi_tab1.
"The lines meeting the condition are respected.
"Note: The source table must have at least one sorted or hashed key.
"Here, the primary key is used
DATA(f1) = FILTER #( fi_tab1 WHERE a >= 3 ).
out->write( data = f1 name = `f1` ).
out->write( |\n| ).
"USING KEY primary_key explicitly specified; same as above
DATA(f2) = FILTER #( fi_tab1 USING KEY primary_key WHERE a >= 3 ).
out->write( data = f2 name = `f2` ).
out->write( |\n| ).
"EXCEPT addition
DATA(f3) = FILTER #( fi_tab1 EXCEPT WHERE a >= 3 ).
out->write( data = f3 name = `f3` ).
out->write( |\n| ).
DATA(f4) = FILTER #( fi_tab1 EXCEPT USING KEY primary_key WHERE a >= 3 ).
out->write( data = f4 name = `f4` ).
out->write( |\n| ).
"Secondary table key specified after USING KEY
DATA(f5) = FILTER #( fi_tab2 USING KEY sec_key WHERE a >= 4 ).
out->write( data = f5 name = `f5` ).
out->write( |\n| ).
DATA(f6) = FILTER #( fi_tab2 EXCEPT USING KEY sec_key WHERE a >= 3 ).
out->write( data = f6 name = `f6` ).
out->write( |\n| ).
"Note: In case of a hash key, exactly one comparison expression for each key
"component is allowed; only = as comparison operator possible.
DATA(f7) = FILTER #( fi_tab3 WHERE a = 3 ).
out->write( data = f7 name = `f7` ).
out->write( |\n| ).
"Using a filter table
"In the WHERE condition, the columns of source and filter table are compared.
"Those lines in the source table are used for which at least one line in the
"filter table meets the condition. EXCEPT and USING KEY are also possible.
"Declaring and filling filter tables
DATA filter_tab1 TYPE SORTED TABLE OF i
WITH NON-UNIQUE KEY table_line.
DATA filter_tab2 TYPE STANDARD TABLE OF i
WITH EMPTY KEY
WITH UNIQUE SORTED KEY line COMPONENTS table_line.
filter_tab1 = VALUE #( ( 3 ) ( 5 ) ).
filter_tab2 = filter_tab1.
DATA(f8) = FILTER #( fi_tab1 IN filter_tab1 WHERE a = table_line ).
out->write( data = f8 name = `f8` ).
out->write( |\n| ).
"EXCEPT addition
DATA(f9) = FILTER #( fi_tab1 EXCEPT IN filter_tab1 WHERE a = table_line ).
out->write( data = f9 name = `f9` ).
out->write( |\n| ).
"USING KEY is specified for the filter table
DATA(f10) = FILTER #( fi_tab2 IN filter_tab2 USING KEY line WHERE a = table_line ).
out->write( data = f10 name = `f10` ).
out->write( |\n| ).
"USING KEY is specified for the source table, including EXCEPT
DATA(f11) = FILTER #( fi_tab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE a = table_line ).
out->write( data = f11 name = `f11` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `14) READ TABLE: Reading a single line by index` ) ).
"Creating and populating an internal table
TYPES: BEGIN OF st_h,
a TYPE i,
b TYPE c LENGTH 2,
c TYPE string,
END OF st_h,
ty_tab_f TYPE SORTED TABLE OF st_h WITH UNIQUE KEY a WITH NON-UNIQUE SORTED KEY sk COMPONENTS b.
DATA(it_j) = VALUE ty_tab_f( ( a = 1 b = 'zz' c = `B` )
( a = 2 b = 'xx' c = `D` )
( a = 3 b = 'yy' c = `F` ) ).
DATA struc_e TYPE st_h.
"In the following example ...
"- a work area is specified as target area.
"- USING KEY is not specified, i.e. the primary table index is used by default.
READ TABLE it_j INTO struc_e INDEX 2.
"Reading into a work area that is created inline
READ TABLE it_j INTO DATA(struc_f) INDEX 3.
"Specifying other target areas: Field symbols and data reference variables
"Here, the target areas are created inline
READ TABLE it_j ASSIGNING FIELD-SYMBOL(<fs_c>) INDEX 1.
READ TABLE it_j REFERENCE INTO DATA(dref_c) INDEX 1.
"******* USING KEY addition *******
"Reading by index and specifying which table index to use
"In the following example, the primary key is specified explicitly and
"addressed using the default name primary_key. It has the same effect
"as the statement below because the primary table index is used by
"default.
READ TABLE it_j INTO struc_e INDEX 1 USING KEY primary_key.
READ TABLE it_j INTO struc_e INDEX 1.
"Specifying the secondary key to use the secondary table index
READ TABLE it_j INTO struc_e INDEX 1 USING KEY sk.
"Using alias names
DATA it_j_alias TYPE SORTED TABLE OF st_h
WITH UNIQUE KEY primary_key ALIAS pk COMPONENTS a
WITH NON-UNIQUE SORTED KEY sk ALIAS sk_alias COMPONENTS b.
it_j_alias = it_j.
READ TABLE it_j_alias INTO struc_e INDEX 1 USING KEY pk.
READ TABLE it_j_alias INTO struc_e INDEX 1 USING KEY sk_alias.
"The following examples use the other key names
READ TABLE it_j_alias INTO struc_e INDEX 1 USING KEY primary_key.
READ TABLE it_j_alias INTO struc_e INDEX 1 USING KEY sk.
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `15) System field setting with READ TABLE statements` ) ).
READ TABLE it_j INTO struc_e INDEX 999.
IF sy-subrc = 0.
...
ELSE.
... "This branch is executed in the example since the line is not found.
ASSERT sy-tabix = 0.
ENDIF.
READ TABLE it_j INTO struc_e INDEX 1.
ASSERT sy-subrc = 0.
ASSERT sy-tabix = 1.
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `16) READ TABLE: Reading a single line using table keys` ) ).
"Creating and populating a demo internal table
TYPES: BEGIN OF st_i,
num TYPE i,
str TYPE string,
char TYPE c LENGTH 2,
END OF st_i.
DATA it_k TYPE SORTED TABLE OF st_i
WITH NON-UNIQUE KEY primary_key ALIAS pk COMPONENTS num
WITH NON-UNIQUE SORTED KEY sec_key ALIAS sk COMPONENTS char.
it_k = VALUE #( ( num = 1 str = `A` char = 'zz' )
( num = 2 str = `C` char = 'yy' )
( num = 3 str = `E` char = 'xx' ) ).
"The following examples use a work area as target. Other target areas are
"possible.
"Primary table key
READ TABLE it_k INTO DATA(struc_i) WITH TABLE KEY primary_key COMPONENTS num = 3.
"Primary table key alias
READ TABLE it_k INTO struc_i WITH TABLE KEY pk COMPONENTS num = 2.
"Secondary table key
READ TABLE it_k INTO struc_i WITH TABLE KEY sec_key COMPONENTS char = 'xx'.
"Secondary table key alias
READ TABLE it_k INTO struc_i WITH TABLE KEY sk COMPONENTS char = 'yy'.
"Reading a line based on keys specified in a work area
"It is a work area containing primary and secondary table key values.
"the line type must be compatible to the internal table.
TYPES st_j LIKE LINE OF it_k.
DATA(pr_key) = VALUE st_j( num = 1 ).
DATA(sec_key) = VALUE st_j( char = 'yy' ).
READ TABLE it_k FROM pr_key INTO struc_i.
"If USING KEY is not specified, the primary table key is used by default.
"Explicitly specifying the primary table key
READ TABLE it_k FROM pr_key USING KEY primary_key INTO struc_i.
"Primary table key alias
READ TABLE it_k FROM pr_key USING KEY pk INTO struc_i.
"Secondary table key
READ TABLE it_k FROM sec_key USING KEY sec_key INTO struc_i.
"Secondary table key alias
READ TABLE it_k FROM sec_key USING KEY sk INTO struc_i.
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `17) READ TABLE: Reading a single line using a free key` ) ).
"Note: Instead if READ TABLE ... WITH TABLE KEY ..., it is ... WITH KEY.
READ TABLE it_k INTO DATA(struc_j) WITH KEY str = `A`.
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `18) Examples for addressing individual components of read lines` ) ).
"Examples for addressing individual components of read lines
"The assertions emphasize the difference of work areas and field
"symbols/data reference variables as target areas. Modifying the
"contents of the field symbols/data reference variables means
"modifying the internal table content.
READ TABLE it_k INTO DATA(struc_k) WITH KEY str = `A`.
struc_k-num = 123.
DATA(comp_b) = struc_k-num.
READ TABLE it_k ASSIGNING FIELD-SYMBOL(<fs_e>) WITH KEY str = `C`.
"Note: The example table is a sorted table with 'num' as part of
"a unique key. The field value cannot be modified.
"<fs_e>-num = 123.
<fs_e>-char = 'hi'.
DATA(comp_c) = <fs_e>-char.
READ TABLE it_k REFERENCE INTO DATA(dref_e) WITH KEY str = `E`.
dref_e->char = '##'.
DATA(comp_d) = dref_e->num.
"It is also possible to specify the dereferencing operator together
"with the component selector.
DATA(comp_e) = dref_e->*-char.
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `19) READ TABLE: COMPARING / TRANSPORTING additions` ) ).
"Comparing fields and specifying fields to be transported
TYPES ty_tab_h TYPE TABLE OF st_i WITH EMPTY KEY.
DATA(it_m) = VALUE ty_tab_h( ( num = 1 str = `Z` char = '##' )
( num = 2 str = `Y` char = 'yy' )
( num = 3 str = `X` char = '##' )
( num = 4 str = `W` char = 'ww' )
( num = 5 str = `W` char = '##' )
( num = 6 str = `V` char = '##' )
( num = 7 str = `V` char = '##' )
( num = 7 str = `V` char = '##' )
( num = 8 str = `V` char = 'vv' ) ).
"******* TRANSPORTING NO FIELDS addition *******
"It is only checked whether the line exists. No target area is specified.
"The system fields sy-subrc and sy-tabix are filled. Check also the
"line_exists and line_index functions.
READ TABLE it_m WITH KEY str = `X` TRANSPORTING NO FIELDS.
ASSERT sy-subrc = 0.
DATA(sysubrc) = sy-subrc.
ASSERT sy-tabix = 3.
DATA(sytabix) = sy-tabix.
READ TABLE it_m WITH KEY str = `nope` TRANSPORTING NO FIELDS.
ASSERT sy-subrc = 4.
ASSERT sy-tabix = 0.
"******* TRANSPORTING ... addition *******
"Specifying fields to be transported; cannot be used with the ASSIGNING
"and REFERENCE additions
READ TABLE it_m INTO DATA(struc_l) INDEX 1 TRANSPORTING num char.
ASSERT struc_l-str IS INITIAL.
"If ALL FIELDS is specified, all fields are assigned, which corresponds to the
"example below.
READ TABLE it_m INTO struc_l INDEX 1 TRANSPORTING ALL FIELDS.
READ TABLE it_m INTO struc_l INDEX 1.
"******* COMPARING addition *******
"- Can be used together with and in front of TRANSPORTING ...
"- Compares the specified components
"- ALL FIELDS compares all components, NO FIELDS compares no components
"- Setting of sy-subrc: 0 is set if the content of compared components is identical,
" otherwise it is 2. Found lines are nevertheless assigned independently of the comparison.
"The following examples use a WHILE loop to read all table lines (sy-index represents the
"index value of the primary table index) into a work area.
"The work area is filled before the read for the comparison. Depending on the comparison
"result (by checking the sy-subrc value), the lines are added to different internal tables
"for demonstration purposes. In addition, the 'num' component value is added to a string.
"The examples explore several syntax options.
DATA struc_m LIKE LINE OF it_m.
DATA it_n LIKE it_m.
DATA it_o LIKE it_m.
DATA nums_subrc_0 TYPE string.
DATA nums_subrc_2 TYPE string.
DATA(subrc) = 0.
"Specifying ALL FIELDS
WHILE subrc = 0.
DATA(idx) = sy-index.
struc_m = VALUE #( num = 7 str = `V` char = '##' ).
READ TABLE it_m INTO struc_m INDEX idx COMPARING ALL FIELDS TRANSPORTING ALL FIELDS.
subrc = COND #( WHEN sy-subrc = 0 THEN 0 ELSE sy-subrc ).
IF subrc = 0.
APPEND struc_m TO it_n.
nums_subrc_0 &&= struc_m-num.
ELSEIF subrc = 2.
APPEND struc_m TO it_o.
nums_subrc_2 &&= struc_m-num.
subrc = 0.
ELSE.
EXIT.
ENDIF.
ENDWHILE.
ASSERT nums_subrc_0 = `77`.
ASSERT nums_subrc_2 = `1234568`.
CLEAR: subrc, struc_m, it_n, it_o, nums_subrc_0, nums_subrc_2.
"Specifying specific fields for the comparison and transport
WHILE subrc = 0.
idx = sy-index.
struc_m = VALUE #( num = 1234 str = `NOPE` char = '##' ).
READ TABLE it_m INTO struc_m INDEX idx COMPARING char TRANSPORTING num.
subrc = COND #( WHEN sy-subrc = 0 THEN 0 ELSE sy-subrc ).
IF subrc = 0.
APPEND struc_m TO it_n.
nums_subrc_0 &&= struc_m-num.
ELSEIF subrc = 2.
APPEND struc_m TO it_o.
nums_subrc_2 &&= struc_m-num.
subrc = 0.
ELSE.
EXIT.
ENDIF.
ENDWHILE.
ASSERT nums_subrc_0 = `135677`.
ASSERT nums_subrc_2 = `248`.
CLEAR: subrc, struc_m, it_n, it_o, nums_subrc_0, nums_subrc_2.
WHILE subrc = 0.
idx = sy-index.
struc_m = VALUE #( num = 9999 char = '##' str = `V` ).
READ TABLE it_m INTO struc_m INDEX idx COMPARING char str TRANSPORTING num.
subrc = COND #( WHEN sy-subrc = 0 THEN 0 ELSE sy-subrc ).
IF subrc = 0.
APPEND struc_m TO it_n.
nums_subrc_0 &&= struc_m-num.
ELSEIF subrc = 2.
APPEND struc_m TO it_o.
nums_subrc_2 &&= struc_m-num.
subrc = 0.
ELSE.
EXIT.
ENDIF.
ENDWHILE.