ABAP On Hana

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 120

ABAP for SAP HANA

सतीष कुमार रे ड्डि एम एन Page: 1


HANA  High Performance Analytic Appliance
High Performance means, HANA performance is very fast because of its Hardware and
Software components and in memory database.
Hardware changes: HANA server will contain 4 layers. Each layer will contain 8 Processors.
Each processor will contain 12 Cores. So total 384 Cores will be there in HANA DB. At a time
384 activities will run at a time.
Software changes: HANA contains columnar, row store database tables. Compressed format in
columnar tables.
Uses of column store
 Less memory usage
 Compress data
Row store:
If we are reading the table information less frequently then Row store will be good. If we are
fetching total table information then also Row store will be good.

Column store:
If we are fetching table data frequently or if we are fetching particular fields data only then
Columnar store will be good.
HANA is memory database: Data will store in RAM. Fetching data from RAM is faster than
fetching data from Database. If the system is shutdown or restarted, then also data won’t remove.
Analytic means, combines the OLTP & OLAP process
Appliance means combines hardware and software technology & change the way of developing
&executing application.
In S4HANA, a few tables merged into single table and a few transactions merged into one
transaction.
XK01/XD01/FK01/FD01 Converted into one new transaction  BP.
MB01/MB11/MB1B transactions are absolute and replaced with MIGO transaction.
MSEG/MKPF/MARD/MBEW/MARC (total material tables) are merged into one new table
MATDOC.
A few tables converted into views like BSIK, BSAK.
A few cluster table / pooled tables converted into transparent table.
SAP has created CDS views for a few tables. If we want to get to know that CDS view name for
the particular table we can find out like this.
Click on Extras (menu button)  Replacement Object.

सतीष कुमार रे ड्डि एम एन Page: 2


If we want to get to know transactions merged into new transaction, we have one table and
program.
Table: PRGN_CORR2
Program: PROFGEN_CORR_REPORT_2
DD09L is the table to get to know all Row store and Column store tables. Pass ROWORCOLST
= ‘R’ and execute the table, table will display all Row store tables.

How to identify we are working on Suit on Hana or S/4 Hana:-


Open SAP system  System  Status  Check the DB (HDB is there or not)  click on
Details (search type button)  Check S4CORE entry is there or not.
If the DB is HDB and S4CORE is available then we are working on S/4 HANA otherwise we are
working on Suit on Hana.
5 Golden rules to keep HANA faster
 Keep the result set small – Number of rows minimize (Use where condition, Min, Max,
Count, check, exit)
 Minimize the amount of data transferred (don’t use select *)
 Minimize the number of database access (don’t use select query with in Loop statement,
User Inner join & for all entries)
 Minimize the search overhead (don’t use index for column store and use index for row
store if it is required)
 Reduce the database load(Use CDS views, AMDP, Don’t use Pool or clustered tables)
Difference between Open SQL & Native SQL
Generally system architecture will be like this – Presentation Layer, Application Layer, Database
Layer (Just assume we are using Oracle DB). Now I’ll write the program in application layer as
Select field1 feild2 field3 from <DB Table> into table <Internal table>.
This is Open SQL Statement. But In Oracle, if we use the above syntax, it will throw error. The
syntax will different here.

In Application Layer, there will be ‘Database Abstraction’. It can get to know that to which DB
we have connected. Whatever we are writing the code in ABAP layer it will convert into Native
SQL (Database understandable format).

For example, we have written the code in the Application layer in Native SQL (Database
understandable format). It is working fine. After a few days, I want to migrate to another
database to DB2. Now the DB2 syntax will be different. If we migrate the programs to DB2, It
will through errors.

सतीष कुमार रे ड्डि एम एन Page: 3


So, we have to maintain the code in Open SQL in the application layer. Automatically Database
Abstraction will convert the code into Native SQL.
Open SQL means, SQL variant built into ABAP language & it only support DML (Managing
data into table from program). Open SQL will not support for a few things (<ABAP 7.4 SP05)
 Not support case expressions
 Not support right outer join
 Not support union
 Not support subqueries in select query
 Not support access to HANA built in functions (DAYS_BETWEEN( ))
 Not support access to HANA views & procedures
 Not support code pushdown
If we want to do code pushdown, we have to follow New Open SQL syntax, which has been
enhanced in SAP net viewer 7.4 SP05. These new syntaxes include Arithmetic, Aggregation &
comparative functions. That allow to perform functions on database layer itself.
To overcome the classical Open SQL, SAP introduce the New Open SQL. New Open SQL is
available from >= ABAP 7.4 SP05.
New Open SQL will allow the below things.
 Support Arithmetic expressions with operators +, -, *, /
 Support Arithmetic functions FLOOR, CEIL, MOD, DIV
 Support CASE expression
 Support Right outer join
 Support Union & Union All
 The maximum number of tables supported in Open SQL JOIN clauses has been increased
to 50
 The maximum number of subqueries supported in an Open SQL statement has been
increased from 9 to 50
 Access to SAP HANA built in functions for example DAYS_BETWEEN()
 Access to SAP HANA view &procedures
Features of ADT (Eclipse / Hana Studio)
 We can work simultaneously on DEV, QAS, PRD.
 Different systems, different landscapes, different types (UI5, Java, ODATA) in a single
development environment.
 Fast search & navigation capability (CTRL + SHIFT + A).
 Supports extensibility objects like CDS Views, AMDP.
 Supports debug & transport features.
 Modularize code blocks
 Code template
Code template means adding something code in one block for reusable.
Steps to create template: click on Windows menu button in ADT ABAP Perspective  Windows 

सतीष कुमार रे ड्डि एम एन Page: 4


Preferences  Search for template. In ABAP Development hierarchy we can see ABAP Templates, click
on that one, click on new button.

Provide name (_SJF), description (Looping statement), Pattern, click on Apply button. In Pattern I’m
maintaining like this.
loop at it_ into _wa.
write:/ wa_ , wa_ , wa_ .
endloop.

Click on Ok button. Now you can use this template anywhere in our programs.
In middle of the program I’m giving like _SJF & click on enter. Automatically the pattern data will paste
here.

Performance check of a program


1. Static Check
 SCI (SAP Code Inspector)
 EPC (Extended Program Check)
 ATC (ABAP Test Cockpit)
2. Runtime Check
 ST04
 ST05 (SQL Trace)
 SE30 / SAT
 ST12

SAP Code Inspector (SCI):


SELECT * FROM vbak INTO TABLE @DATA(lt_vbak).

SELECT * FROM vbap INTO TABLE @DATA(lt_vbap)


FOR ALL ENTRIES IN @lt_vbak
WHERE vbeln = @lt_vbak-vbeln.

LOOP AT lt_vbak INTO DATA(ls_vbak).


LOOP AT lt_vbap INTO DATA(ls_vbap)
WHERE vbeln = ls_vbak-vbeln.

सतीष कुमार रे ड्डि एम एन Page: 5


WRITE:/ ls_vbak-vbeln,
ls_vbak-kunnr,
ls_vbap-matnr,
ls_vbap-posnr.
ENDLOOP.
ENDLOOP.

Open the program  click on Program menu button  Check  Code Inspector.

Here we are not maintaining where condition for VBAK table. We can see that in code inspector.
If we extend all errors in code inspector, we can get to know the performance issues.
If we want to check more than one program at a time, then we need to execute SCI T.Code.
I’m taking one more example for PO information. We will check performance check (SCI) for
previous program (ZSO) and the current program (ZPO).
REPORT ZPO.
select * from ekko into table @data(lt_ekko).

loop at lt_ekko into data(ls_ekko).


select single lifnr, name1 from lfa1 into @data(ls_lfa1)
where lifnr = @ls_ekko-lifnr.
write:/ ls_lfa1-lifnr, ls_lfa1-name1.
endloop.

Execute SCI transaction.

सतीष कुमार रे ड्डि एम एन Page: 6


Provide something name in Object set to provide more than one program name. Click on create
button.

In select Object Set tab, deselect the Class/Interface checkbox & Function Group checkbox.
Click on Free Obj choice tab.

सतीष कुमार रे ड्डि एम एन Page: 7


Select the ‘Select Object Set’ tab. Provide the Object Type as ‘Prog’. If you want to check
Function module or class you can click on F4 button select it. Provide the program names in
Object Name. Click on save button (Ctrl + S). Click on back button. Copy the Object name.
Screen will go to SCI transaction first screen.

Provide the Inspection name. Click on create button.

In the check variant, provide the name as PERFORMANCE_DB (we are checking the
performance). We have created one object set named as ZTEST_SO_PO. In that one we have
mentioned 2 program names (ZPO & ZSO). Just paste that object set name here.

सतीष कुमार रे ड्डि एम एन Page: 8


If we want to execute for any TR then select Request / Task radio button and provide the TR
number. If we want to execute for only one program or one class or one function group or
function module, then select ‘Single’ radio button, select which object you are execution
(program/class/FM/FG), provide that name.
Click on execute button (top side). Click on Result button.

We can get to know the errors like this.

Extended Program check:


For the last program we can check extended program check. Click on Program menu button 
check  Extended program check  click on execute button (F8).

If we double click on errors, we can get to know the performance issues.


ATC Check:
For the last program we can do ATC check. Click on Program menu button  check  ATC
Check.

सतीष कुमार रे ड्डि एम एन Page: 9


In real time, we should avoid Priority ‘1’ and ‘2’ issues. If we double click on Check Title, we
can get to know the exact issue.
ST05 (SQL Trace)
To perform this trace, we need to execute ST05 T.Code  Select SQL Trace check box.

If we want to activate the trace for particular user or particular table, click on Activate Trace with
Filter button. Otherwise click on Activate Trace. Click on enter button. We can get the status as
below.

सतीष कुमार रे ड्डि एम एन Page: 10


Now execute our program in a separate session. After execution open our ST05 screen. Click on
Deactivate Trace button. Click on Display Trace button. Provide proper inputs (user or date
range). Click on execute button.

We can see the issues here.


SAT / SE30
Execute the T.Code SAT. If you want to check performance for a transaction, provide the
transaction name or program name.

Select the ‘Get names for internal tables’ check box. Provide the variant name and click on
‘New’ button which will be under that variant name.

सतीष कुमार रे ड्डि एम एन Page: 11


Select the ‘Statements’ tab. Select Read Operations check box and Change Operations checkbox
under internal tables. Client Variant menu button  Save (Ctrl + S). Click on back. Click on
Execute button. If you have any input parameters, it will ask for input parameters (select-options
and parameters). Click on execute button. It will display the output. Click on back button.

Click on Hit List tab. We can see for each statement how much time is consuming.
Instead of SE30 transaction, we are using SAT transaction now.
ST12
Execute ST12 transaction. Click on ‘current mode’ button. Select the radio button program and
provide the program name. Click on ‘Execute / start trace’ button. It will execute the program.
Click on back button. Select our log as shown in the below image.

सतीष कुमार रे ड्डि एम एन Page: 12


Click on ‘ABAP trace’ button. It will display the log information. We can double click on the log
to display detailed information.

Problems with ST05 / SE30 / SAT / ST12


These are tools designed to take trace at process level & hence, even if we enable for a small
amount of time it collects huge amount of data. Since these trace runs synchronously, it creates
huge load on the system.
Production system will not allow the above transactions because it will run synchronously &
creates huge load on the system.
SAP is providing the below tools to check performance in production system.
 SQLM (SQL Monitor)
 SQLMD (SQL Monitor Display)
 SWLT (SQL Performance Tuning Worklist)
These tools runs asynchronously & collects the traces. Hence these are recommended to run into
production system.
SQLM:
Execute SQLM transaction  Click on ‘All Servers’ button. If you want to check for a specific
server, click on ‘Select Server’ button. Provide the Expiry date and time. Click on ‘Continue’
button.
After expiry time reached, clicked on ‘Display Data’ button. Provide the inputs as date range,
program names, click on execute button.

सतीष कुमार रे ड्डि एम एन Page: 13


We can see the program names which are executed in given time.
This will be very useful to identify which program is executing frequently and how much time
consuming in production system.
SWLT:
In SQLM transaction, we can see the program names and consumption time. If we want to get to
know the performance issue syntaxes then we have to go to SWLT. Before going to this
transaction, execute SQLM transaction and click on ‘Export Data’ button. Save the data in one
ZIP file.
Execute SWLT transaction  Provide the inputs if you have like program name or object type or
package. Click on SQL Monitor tab  Click on ‘Manage / Create Snapshots’ button. In Data
source, select the file location which you have downloaded from SQLM transaction. Click on
‘Create Snapshot’ button  Click on Allow. Click on back button and click on execute button.

SAP Business Suit ECC 6.0

Client Application Server Database Server

UI: SAP GUI RDBMS: Supported by SAP


DB
Select KUNNR Native (Oracle, MS SQL)
INTERF
NAME1 SQL
ACE
From KNA1 into
table IT_KNA1

Open SQL

ECC is 3-tier architecture (Presentation Server, Application Server and Database Server). We
will write something code in the Application server to fetch data from Database. We will write
OPEN SQL syntax in application server. DB Interface will convert this OPEN SQL syntax into
Native SQL, fetch the data and send it to Application server.

सतीष कुमार रे ड्डि एम एन Page: 14


SAP Business Suit for SAP HANA

Client Application Server Database Server

UI: SAP FIORI


DB HANA DB
Enhanced Open NativeSQL,
INTERF
SQL, HANA Views,
ACE
CDS Views, Stored
AMDP Procedure
New Open SQL

This is also 3-tier architecture. In presentation server, we will use SAP FIORI and Database as
HANA. In Application server lot of changes are there. We have to follow New Open SQL
syntax, create CDS Views and AMDP. If we create and activate CDS view, automatically
HANA view will create in DB layer. If we create, activate and run the AMDP, automatically
Stored Procedure will create in DB layer.

Differences between Data to Code, Code to Data


Data to Code (Before SAP HANA) Code to Data (With SAP HANA)

Data Integration
Select Query
Loop
Calculation
End loop

Medium data
Huge data
transfer transfer

New Open SQL,


CDS Views,
AMDP
Data Integration
Database Database
RDBMS: Any DB supported by SAP SAP HANA
(Oracle or MS SQL)

सतीष कुमार रे ड्डि एम एन Page: 15


Before SAP HANA, We are fetching the data into Application server and doing the calculations
in Application server. Here we have to fetch unwanted data (supporting data) also for
calculations. Coming to Code to Data, we are doing all calculations in DB (CDS, AMDP) and
only result we are sending to Application server.

Differences between Bottom up approach, Top down approach


In Bottom up approach, we need to create HANA View in DB, then create Expose view on top
of that HANA view. Then we can use it in ABAP layer. We need to create Database Procedure
in DB and need to create Procedure proxy in ABAP layer. In HANA DB, we need to create
Delivery Unit (nothing but TR in our terms) at the same time we need to create TR in
Application server. If we miss something here, It will go to dump. For single object we need to
create two times.

How to save move the Information Model (Hana Modelling Views) from DEV to QAS

Need to create the Information Model (Calculation View) in one package. Need to create
Delivery Unit. Open Hana Modeller Perspective. Click on Windows → Show View → others →
type ‘Quick View’ in search bar click on enter button. Click on Quick View Option. One
sunscreen will display at right side of your screen. Click on ‘Delivery Unit’. Select the user name,
click on next button. It will display all Delivery Units. If you want to use existing one, need select
the Delivery Unit name otherwise click on ‘New’ button. If ‘New’ button is appearing, expand the
window width. Click on ‘New’ button. Provide the name (Delivery Unit Name), click on ‘OK’
button. Select our Delivery Unit name, Click on ‘Add’ button. Select our package where we have
saved the Information Model. Click on ‘Finish’ button.

Create Hana Transport Container


Open ABAP Perspective.

Click on New button (down arrow button), click on Other. Search for Hana Transport Container.
Click on Hana Transport Container, click on ‘Next’ button. Provide the Hana Delivery Unit
Name. Click on ‘Next’ button, Select the TR, Click on Finish button. Click on ‘Take snap shop
and save’. Now the Delivery unit will save in TR.

सतीष कुमार रे ड्डि एम एन Page: 16


In Top Down approach, if we create CDS view in ABAP layer (Application server),
automatically HANA View will create in DB. If we create AMDP in ABAP Layer,
Automatically Database Procedure will create in DB. We can create TR in Application server.
Not required Delivery unit here.
AS ABAP AS ABAP

External Procedure HANA Transport CDS AMDP Standard ABAP


Views Proxy container Views Transport (CTS)

Exposin Exposin Transport Deploy Deploy


g g
HANA HANA Delivery Unit HANA Database
Views Procedure Views Procedure

SAP HANA Bottom Up Approach SAP HANA Top Down Approach

Possible Approaches based on AS ABAP


>= 7.4 SP05 or above CDS View,
AMDP,
New Open SQL

सतीष कुमार रे ड्डि एम एन Page: 17


Below 7.4 SP05 HANA Views (Attribute, Analytic, Calculation View),
HANA DB Procedures
Need to create External view, Procedure proxy in AS ABAP layer
Below NW 7.4 SPS HANA Views and Database procedures consumed using Native SQL
& ADBC in AS ABAP

सतीष कुमार रे ड्डि एम एन Page: 18


Information Model
Main purpose is to hide the technicalities to select data & make it easier for business users to
model their data which can be pulled without technical knowledge, just data base functional
knowledge is sufficient.
Advantages:
It is used to convert linear structure to a multi dimension structure without knowing technical
language.
These are process of converting source data (in tables) into business understandable format.
They also make use of hardware advancements in HANA
If we define information models inside HANA Database, we can also reduce the data transfer
between database and application layer.
Complex logic as well as transformation executed in database layer.
Types of Information Model
 Attribute View
 Analytical View
 Calculation View
HANA DB will contain SQL Optimizer & a few Engines. If we write something select query in
HANA SQL prompt, it will trigger SQL optimizer to perform that select query then it will go to
one engine to fetch and do calculations & provide the output.
Mostly Attribute view will work on Join Engine, Analytical view on OLAP Engine, Calculation
view on Calculation Engine.

Attribute View: It will contains Data foundation & Semantics. Data foundation means we can
provide tables with selections, joins & condition in this area. Semantics means it will contain
more information about this data model like mentioning key fields, hierarchies
Content: It is collection of packages which we add different development objects including
information models.

Creation of attribute view: -


Login to the server & open the HANA studio. We already created one package & sub package.
Right click on sub package  new  attribute view. Provide the name, label (as description).
Click on finish. We will see the data foundation, semantics in scenario pain. If we select data
foundation we can see the details pain, output pain & properties pain.

सतीष कुमार रे ड्डि एम एन Page: 19


A data foundation is an area to create foundation for data. This is the place where we
define relation between tables. When we select data foundation we can see one ‘+’ symbol (add
object). Just click on add objects. Enter the table name. Select the table name. Click on ok.
For adding another table I’ll follow one more method. Expand catalog. Expand our
schema. Expand tables. Drag and drop the table whatever you want from left side to right side.
We need to join the tables by dragging fields from one table to another table. In the
properties window, we have to select join type as text join.
Text join is a join that gives descriptions based on user session. Whenever we give the
join type as text join, we have to select language column as SPRAS. Select another join, provide
the join type, language key as previous.
If you select a join type as text join, remaining joins also will be text join automatically in
the same table only. We have to select the fields whichever we want to display. After selecting,
we can see those fields in output pain.
Now click on semantics. The selected columns will be available in semantics. We have at
least one key field. So we can select the key check box for the fields which field you want key
field.
For example I’ve KUNNR, NAME1, LAND1, LANDX, REGIO, BEZEI fields. KUNNR
is the customer number. So I want customer name beside the customer number. So I select
NAME1 on the label column of KUNNR. Now customer name will display in the output beside
the customer number. Now I don’t want to display the customer name once again. We have
NAME1 in our list of fields. So we will select the hide check box for NAME1 field. So customer
name will display only once beside the customer number. We have to do like this for all. Now
check the view and activate the view. Once we activate the view, click on show log icon which is
top right. You can see the status here.
Expand our system in left panel. Expand content, expand our package and sub package.
Expand attribute view. Now we can see our attribute view here. Right click on our attribute view.
Select data preview. Click on Raw data button which is on top. Now click on add filter button.
Select our filter field name. Click on show list of values. Select the condition values. Click on
ok. Click on execute button. You can see the data.
Sub types of attribute view:
 Standard
 Time
 Derived
Time attribute view is used to analyze transaction data based on different time dimensions.
We have one standard schema ‘_SYS_BI’. For all tables related to time.
Right click on our package  new  attribute view. Provide name, label & subtype as time.
Select the calendar type as Gregorian. Provide granularity as year. Click on finish button. If we

सतीष कुमार रे ड्डि एम एन Page: 20


select the auto creation check box, in data foundation we can see one table & fields
(M_TIME_DIMENSION_YEAR). This schema is under _SYS_BI package.
If you create another attribute view with sub type as time & granularity as date, we can see
different table i.e. M_TIME_DIMENSION in data foundation. Click on data foundation. The
schema is under _SYS_BI.
Now expand the catalog. Expand _SYS_BI schema. Expand tables. You can see the
tables like M_TIME_DIMENSION, M_TIME_DIMENSION_MONTH,
M_FISCAL_CALENDAR.
SAP has given those tables as empty.
Right click on table  delete. Select the radio button of delete all rows. Click on ok. Refresh it.
Table will empty. Click on window menu button in the menu bar  perspective  reset
perspective. Click on yes. Click on open perspective icon which is top right. Select SAP HANA
modeler. Click on ok. Once you click on ok then we can see one option. i.e. quick view at top
right. Click on generate time data in quick view. Select our system name. Click on next. Provide
from year (2000) & to year (2017). Granularity as day. Calendar type as granularity. Click on ok.
Now expand SYS_BI schema. Expand tables. Right click on M_TIME_DIMENSION  open
data preview. Click on analysis. Select year, drag & drop that to label axis. Now open time
attribute which is in our package. Right click on the attribute view  display. You can see the
data. Double click on data foundation. You can see DATE_SQL & DATE_SAP columns.
DATE_SAP is for SAP data base & DATE_SQL for NON-SAP data base.
Derived attribute view: -
It’s also known as reference attribute view. It is nothing but alias of attribute view.
If you create derived attribute view, the view will display the pink color ribbon on top.
We can’t edit anything here. In the derived attribute view, you see the base attribute view name
in the properties pain.
We can’t edit an attribute view which is derived & copied from different attribute view. But
whenever we copy a standard attribute view in another standard attribute view, we can edit in
that.
Design time filter: These are the filters which execute before a join condition. If you want to give
filter before join condition then we go for design time filter. Design time filters are also known
as constraints.
Create an attribute view. Take only one table in data foundation (T005T). Select two fields
(LAND1, LANDX). Right click on SPRAS  Apply filter. Provide the value as ‘E’. Click on
ok. Click on validate & save activate. Right click on our attribute in left side  data preview.
Click on raw data button. Now we can see the LANDX in English language. Right click on our
system name in left side  properties. Click on additional properties tab. Change the local as
Chinese. Click on apply, ok.

सतीष कुमार रे ड्डि एम एन Page: 21


Right click on our attribute  data preview. Click on raw data. Now we can see the LANDX
values in English only.
If you want to display the output in system language we have to give the filter as
$$LANGUAGE$$ instead of ‘E’. Now we will get the data as per system language.
Whenever we activate any attribute view, automatically one column view is generated by
system. These column views are also known as runtime views. These column views will be in
_SYS_BIC.
Attribute views are reusable dimensions used to join Master data tables. Attribute views execute
on a join engine. Join engine is optimized to process complex join.
We can’t provide the multiple filters on a single field, if we want to give multiple filters on a
single field then we have to take that table multiple times and give the condition.
If we create any Attribute view or Analytical view or calculation view in HANA DB, we can’t
see directly in ABAP layer. First we have to create one View Proxy in ABAP Layer. But View
Proxy we can’t create directly in SAP GUI. We can create it in HANA Studio ABAP
Perspective. Open ABAP perspective in HANA Studio  select our package  Right click on it
 New  Other Repository Object. Expand dictionary  Select dictionary view. Provide name,
description. Select external view radio button. Click on HANA view Browse button & select the
HANA view. Click on Next button.
We have created on calculation view in HANA DB by using Delivery unit. We have created one
view proxy in ABAP layer by using that calculation view in one TR. If we move the TR to QTY
system, it will be fail in QTY system. Because the Calculation view is not moved to QTY
(Delivery unit did not move to QTY yet). Here some dependency will be there.
We can lock TR & Delivery unit in ABAP HANA Transport container. We can move it to QTY
system. At that time HANA objects & ABAP objects will move at a time. If we don’t want these
type of dependencies, simply we can go to CDS view.
If we create one CDS view in ABAP layer, automatically it will reflect in HANA DB, so not
required to create any view on database. If we move TR to QTY system CDS view will move &
automatically it will reflect in database also.

Analytical view
Analytical views are the
multidimensional views or OLAP
cubes. Using analytic views you can
analyze values from a single fact
table that is based on the related
attributes from data foundation and attribute views
Creation of Analytical view: Right click on the package  New  Analytic view. Provide
name, label and click on finish button.

सतीष कुमार रे ड्डि एम एन Page: 22


Data foundation is a place to maintain the relationship between the tables. We can take more
than one table but the measures should be taken from a single table.
Star Schema is a place to maintain the relationship between the Attribute views. First we join the
physical tables in Attribute views. After that we join the views in Star Join.
Semantics means, it will contain all selected fields. We have to maintain measures, dimensions
in this place.
Once you have selected fields, click on Semantics. Provide Key field, measures and dimensions.
Click on check button, active button.
To display the output, right click on our analytic view name  select Data preview.

Calculated Column: Calculated columns are used to add one column to the output with the
values which are calculated by a formula.

Select new calculated column folder as shown in the above image. Provide name, label, data
type, length, scale, column type, formula. Click on validate syntax. It will show one message
either it is success or failure also. If it is success, click on ok button.

सतीष कुमार रे ड्डि एम एन Page: 23


Restricted columns:
Restricted columns are used to display one more column in the output with restricted values
only.

Here I’m giving the column name as US_CUST_NETPRICE. If the condition satisfy, then only I
want to display the NETWR in the new column.

सतीष कुमार रे ड्डि एम एन Page: 24


Output will come this. For Indian customers, it is not showing any value. For ‘US’ customers, it
is showing the values.

Calculation Views:
Calculation views are used to achieve multiple star schemas means multiple fact tables
surrounded by multiple dimension tables.
How to create Calculation views:
Right click on package  New  Calculation view. Provide Calculation view name, label and
type as Graphical, select Data Category as Dimension. Click on Finish button.

Here, Data category is containing as Dimension, Cube, Cube with Star join. First we will try with
Dimension.

Default node for Calculation view – Dimension is Semantics, Projection.


Here Projection is allowing only one table or one attribute view or one Analytical view or one
calculation view.
Here if we take measure fields in table level, it will consider as dimension in semantics node.
You can see the below screen.

सतीष कुमार रे ड्डि एम एन Page: 25


Here NETWR is the Measure. But it is displaying as dimension. We should not change this one.
If we want to add more than one table in this view, through projection, it is not possible. So we
have to take join as shown in below.

In the Join also we can add 2 tables / attribute / analytical / calculation views. If we want join more
tables, then we have to drag and drop one more join. In that join we have to take one more table &
link from second join to first join. In each & every join we have to select the fields. If we want to
add the fields to semantics in a single shot, right click on that field  Propagate to semantics

सतीष कुमार रे ड्डि एम एन Page: 26


In the Dimension Calculation View, by default ‘Default Client’ will select as ‘Session Client’ in
the Semantics node  View properties tab. Now we have to change this to ‘Cross Client’ as shown
in the below image. In real time, we have to keep ‘Session Client’ only.

I can take two projections also in a single Dimension Calculation view. By default one projection
will come while creation of a Dimension Calculation view. Now I can add Second projection also.

सतीष कुमार रे ड्डि एम एन Page: 27


Here there is no filter option. If I open the Secondary Projection, it will display like this.

Here, we can add Filter. This is the main difference between Primary and secondary projections.
Here we can drag and drop the Union also. Union can support more than one table / view. But it
will combine all sources information in a single place.

Cube Calculation view


Default node for Cube Calculation view is Semantics, Aggregation.
In Aggregation also we can add only one table or view.

सतीष कुमार रे ड्डि एम एन Page: 28


If we want to add more tables in this view, then we have to drag and drop join as shown in
Dimension Calculation view. Here also we can add more than one aggregation nodes. Difference
is in standard aggregation, we can’t filter for a field, but in secondary aggregation we can apply
filter.
The main difference between Projection & Aggregation is Projection is working like Attribute
view (all fields are dimensions only), Aggregation is working like Analytical view (we can add
dimensions, measures (max, sum, min, count possible for measure)).

Cube with Star Join Calculation view:


Default node for ‘Cube with Star join’ is Semantics, Star Join. Here Star join can accept more than
one Dimension Calculation views only.

If we want add any tables, we can drag and drop join or projection or aggregation.

Rank:
Rank is used to give ranks to the output data. My requirement is, I want to give ranks based on net
value in sales order wise.
Drag and drop the Rank to the main area. Provide table or view in that rant.

सतीष कुमार रे ड्डि एम एन Page: 29


Provide a few details in right side of the screen as shown in the above image. Mostly we sort the
data on descending. Threshold means, how many ranks we want to display here that number we
have to provide. Order by means we are giving ranking based on one measure, that measure fields
we have to provide here. Partition by column means, we have to provide field name which will
divide the ranking in groups. If we want one separate column in the output to get to know the
ranking, then we have to select ‘Generate Rank Column’ check box. Click on aggregation, select
the fields, click on semantics node, provide the data types, key field, click on activate.

We can create Calculation view in two ways


Graphical
SQL Script (CE Function, Pure SQL)

सतीष कुमार रे ड्डि एम एन Page: 30


If we are using CE Function views, then it will not go to Optimizer. Total calculation will done
inside the Calculation engine. If we go for Graphical view, it will trigger Database Optimizer then
it will execute in calculation engine. So the performance will be low here as compare with CE
Function view. If we take Pure SQL View, it will trigger SQL Script optimizer then it will go to
calculation engine. The performance for this one also little bit low compare with CE Function
View.

How to use Attribute view in ABAP (View Proxy)


Open ABAP perspective  Right click on server  New  Other  search for Dictionary
view and select it  Click on Next button.
Pro

Provide Package name, Name of the view, description, Hana View as ‘package.view_name’
(click on browse, provide attribute or analytical / calculation view). Click on Next button.
Click on Finish button, click on Activate button.

सतीष कुमार रे ड्डि एम एन Page: 31


SQL Script
SQL Script we can write in Containers. Container means it the place where can write SQL
Script.
We can write SQL script in containers are 3 types.

Anonymous Block means, we can use it for testing purpose just use and through. It will not
contain any name. It will not save anywhere in server and no name assigned to it. If we execute
it, it will compile every time so it will take some time for execution.
Procedure means, it will store permanently in database with something name. It will be very fast
execution. Because it will compile procedure for the first time, second time on wards it will not
compile, directly execute the procedure.
UDF means, we can write aggregate functions here.

Anonymous Block:
DO ( OUT X INT => ? )
BEGIN
DECLARE A INT = 10;
DECLARE B INT = 2;
DECLARE C INT = 0;
C = A + B;
X = C;
END;

Here I’ve started with ‘DO’ statement. If we have any input parameters or output parameters we
have to maintain here only DO ( IN A INT => ? OUT C INT => ? ).
‘DECLARE’ is the statement to declare variables.
If we don’t maintain variable value like
Declare A INT;
system will consider as ‘A’ is one integer data type variable. It will contain null value. We can’t
execute any line will null value. It will not show any error message if we pass null value. Output
will display like ‘?’.

सतीष कुमार रे ड्डि एम एन Page: 32


If we are declaring anything in input / output parameters, not required to declare it in the body
once again. If declare, it will not through error, output will come as ‘?’.
do ( in a int => ?, in b int => ?, out c int => ? )
begin
c = a + b ;
end;

By using the above syntax, we can give input parameters (as parameter).

Note below points before writing the SQL Code:


1. Declaring any variable it automatically initialize with Null value. So we must initialize
something value.
2. Statement will close with semicolon (;)
3. SQL Script is not case sensitive.
4. Never use ‘:’ before any assignee variable
:C = :A + :B; -- Here we should not keep ‘:’ beside ‘C’. It should be C = :A + :B;

Procedure
drop procedure lr_pr1;
create or replace procedure lr_pr1( out c int )
language sqlscript
default schema "HANAUSER"
reads SQL DATA
as begin
declare a int = 10;
declare b int = 20;
c = :a + :b;
end;

Drop Procedure means, deleting the procedure.


Create or replace procedure means, system will check that procedure is available or not in the
system. If the procedure is not available, it will create new procedure. If the procedure is
available, it will change the existing procedure logic.
Language, default schema, reads SQL DATA(please maintain in capital letters) are optional. We
can write code other than sqlscript also here.
create or replace procedure lr_pr1( in a int, b int, out c int )
as begin
c = a + b;
end;

We can take input parameters also as shown above.


If Condition in Procedure:
create or replace procedure lr_pr2( in a int, out result nvarchar(10) )
as begin

सतीष कुमार रे ड्डि एम एन Page: 33


if mod( a, 2 ) = 0 then
result = 'Even' ;
else
result = 'Odd' ;
end if;
end;

Do While in a procedure
create or replace procedure lr_pr3( in a int, out result nvarchar(10) )
as begin
declare b int = 0 ;
result = 0;
while ( b < a ) do b = :b + 1 ;
result = :result + :b ;
end while;
end;

If we don’t write ‘RESULT = 0’ in 4th line, the output will display like ‘?’. Because we are using
that ‘result’ field as input as well as output. If we are using it as input, then the initial value
should be null. So we need to pass something value to it.
Table Types declaration for a procedure:
drop type tt_kna1;
create type tt_kna1 as table ( kunnr nvarchar(10),
name1 nvarchar(35),
ort01 nvarchar(35) );

‘Create or replace type’ option is not there. So first we are dropping (deleting) the ‘type’ then
creating the ‘type’.
We can see this table type under schema name  Procedure  Table types.
Use table type in a procedure:

create or replace procedure lr_pr4( out result tt_emp )


as begin
result1 = select emp_id, emp_name from hanauser.employee1 ;
result = select * from :result1;
--declare result2 tt_kna1;
--result2.kunnr[1] = '1';
--result2.name1[1] = 'Gayatri';
--result2.ort01[1] = 'Bangalore';
end;

In the 3rd line, I’ve mentioned like Result1 = select query. But I didn’t declare this temporary
table (internal table in SAP terms). Automatically system will create one temporary table (like
inline declaration) and store the result.
In the 4th line, I didn’t mention result = result1. It should not work here. One more time I’m
writing select query on top of temporary table. That is why I’ve mentioned ‘from table’ like
‘:result1’.

सतीष कुमार रे ड्डि एम एन Page: 34


I’ve kept some in comment. If we want to declare any temporary table locally & fill the data in
temporary table then we can follow the commented code.
Use table type without declaration & Fill internal table manually
create or replace procedure lg_pr6( out lt_emp table( emp_no int, emp_name
varchar(40) ) )
as
begin
LT_EMP.emp_no[1] = 1;
lt_emp.emp_name[1] = 'Gayatri';
--second record
lt_emp.emp_no[2] = 2;
lt_emp.emp_name[2] = 'Lakshmi';
end;

Fill internal table Manually with multiple records


create or replace procedure lr_pr8( out it_emp table( emp_no int, emp_name
nvarchar(30) ) )
as begin
--:it_emp.insert( (1, 'Gayatri'), 1 );
--:it_emp.insert( (2, 'Sathish'), 2 );
declare tot_records int;
declare i int;
lt_emp = select emp_id, emp_name from employee1 where mandt =
session_context(client);
tot_records = record_count( :lt_emp );
for i in 1..tot_records do
:it_emp.insert ( ( :lt_emp.emp_id[i], :lt_emp.emp_name[i] ), i );
end for;
end;

call lr_pr8( ? );

Here by using this syntax, we can maunually fill internal table line by line.
:it_emp.insert( (1, 'Gayatri'), 1 );
If we want to fill internal table by using another internal table(select query data), we can write
like this
:it_emp.insert ( ( :lt_emp.emp_id[i], :lt_emp.emp_name[i] ), i );
Session_context(client) is the system variable which will contain the current client number.
Session_contest(applicationuser) is the system variable which will contain current user
name.

Exception Handling
create or replace procedure lg_pr7( in x int, in y int, out z int )
as
begin

सतीष कुमार रे ड्डि एम एन Page: 35


declare exit handler for SQLEXCEPTION
SELECT ::SQL_ERROR_CODE AS ERROR_CODE,
::SQL_ERROR_MESSAGE AS ERROR_MSG
FROM DUMMY;
z = :x / :y;
end;

If we divide any value with zero it will go to dump in ABAP editor. In SQL also, it will not show
any output. To skip it or to handle this exception we can write the code as above procedure.
DECLARE EXIT HANDLER FOR SQLEXCEPTION
By using the above statement system will handle the exception. If we want to display the
exception code, exception message we can write like
SELECT ::SQL_ERROR_CODE as ERROR_CODE, ::SQL_ERROR_MESSAGE as
ERROR_MSG from DUMMY;
Update internal table based on index number (read table index)
CREATE OR REPLACE PROCEDURE LG_PR1( OUT IT_KNA1 TT_CUST )
AS BEGIN
DECLARE LV_IND INT;
IT_KNA1 = SELECT KUNNR, NAME1, ORT01 FROM KNA1;
lv_ind = :IT_KNA1.SEARCH( (KUNNR), '0010100004' );
IT_KNA1.ORT01[LV_IND] = 'CHENNAI';
END;

Cursor
CREATE or replace procedure proc_test7( in p_land1 nvarchar(3), out lt_kna1
table ( kunnr nvarchar(10), name1 nvarchar(35), ort01 nvarchar(35) ) )
as begin
declare ev_kunnr nvarchar(10);
declare ev_name1 nvarchar(35);
declare ev_ort01 nvarchar(35);
declare lv_ind int ;
--declare cursor
declare cursor c1
for select kunnr, name1, ort01 from saphanadb.kna1
where land1 = :P_LAND1;
--open cursor
open c1;
--fetch data
for lv_ind in 1..500 do
fetch c1 into ev_kunnr, ev_name1, ev_ort01;
if c1::NOTFOUND THEN
return;
end if;
lt_kna1.kunnr[lv_ind] = ev_kunnr;
lt_kna1.name1[lv_ind] = ev_name1;
lt_kna1.ort01[lv_ind] = ev_ort01;
end for;
/*fetch c1 into ev_kunnr, ev_name1, ev_ort01;

सतीष कुमार रे ड्डि एम एन Page: 36


lt_kna1.kunnr[2] = ev_kunnr;
lt_kna1.name1[2] = ev_name1;
lt_kna1.ort01[2] = ev_ort01;
fetch c1 into ev_kunnr, ev_name1, ev_ort01;
lt_kna1.kunnr[3] = ev_kunnr;
lt_kna1.name1[3] = ev_name1;
lt_kna1.ort01[3] = ev_ort01; */
--close cursor
CLOSE C1;
end;

Debug SQL Code


Select Debug perspective  click on Debug icon (down arrow button) Click on Debug
Configuration as shown in below screen shot.

If you click on Debug Configuration, the below screen will open.

Click on New_configuration button  Select Procedure to Debug radio buttonselect Catalog


Schema from drop down  click on Browse  expand our schema, select our procedure 
click on Apply button  click on Debug button  Click on save button.

सतीष कुमार रे ड्डि एम एन Page: 37


Open the procedure  keep the break-point  click on debug icon  select debug
configuration. It will go to debugging screen. There is no concept of F5, F6, F7 options. Only F8
will work here.
Check internal table is empty or not
create or replace procedure lg_pr2( out is_empty varchar(20) )
as begin
it_mara = select * from mara;
if is_empty(:it_mara) then
is_empty = 'Empty';
else
is_empty = 'not empty';
end if;
end;

Here IS_EMPTY is fixed variable. We can’t change this name to check the internal table is
empty or not.
Create a table from procedure
CREATE procedure lg_pr3
as begin
drop table comp_info;
create table comp_info(bukrs varchar(4), butxt varchar(40), ort01 varchar(40)
);
insert into comp_info values( '1000', 'Cognizant', 'Bangalore' );
insert into comp_info values( '2000', 'CGI', 'Bangalore' );
insert into comp_info values( '3000', 'TCS', 'Bangalore' );
end;

Insert values into table from internal table (procedure level)


create or replace procedure lg_pr4
as begin
declare lt_t001 table like tt_t001;
:lt_t001.insert( ( '4000', 'TCS', 'Hyderabad' ), 1 );
:lt_t001.insert( ( '5000', 'Cognizant', 'Chennai' ), 2 );
:lt_t001.insert( ( '6000', 'CGI', 'Hyderabad' ), 3 );
insert into comp_info select * from :lt_t001;
--insert into comp_info( BUKRS, BUTXT ) select BUKRS, BUTXT from :lt_t001;
end;

we can insert particular field information in the table (by using internal table) as below.
insert into comp_info( BUKRS, BUTXT ) select BUKRS, BUTXT from :lt_t001;

Create a table in graphical way


In Hana modelling perspective expand catalog  expand our schema  Right click on tables
folder  Click on New table.

सतीष कुमार रे ड्डि एम एन Page: 38


Provide the table name, Schema name, table type as column store or row store, provide field
names and provide at least one field as key field. If you want add any new field click on ‘+’
button, click on activate (F8) button to create a table.
Modify data in table
upsert comp_info select * from :lt_t001;

Upsert will work like if key data is available in the table, it will modify the data. If the key field
value is not available then it will insert the data into table.
How to export Procedure to ABAP layer (Application server)
We can export Procedure to Application server in 2 ways
 ADBC (ABAP Data Base Connectivity)
 Database Procedure Proxy

सतीष कुमार रे ड्डि एम एन Page: 39


AMDP (ABAP Managed Database Procedure)
HANA DB understand the SQLSCRIPT. It will not understand the Open SQL.
Using the AMDP framework has the following advantages
 SQLSCRIPT source code is edited and managed in the ABAP Repository Object. Earlier
we need to edit or manage at the DB level only (for stored procedure before 7.4 SP05).
 By using AMDP, we can read, modify, update the records in DB
 Transport Lifecycle management is very smooth (there is no need of Delivery unit,
procedure proxy, HANA Transport Container)
 It’s a code push down technique
 Even though we don’t have access to operate DB, we can write the stored procedures in
DB
 We can write complex business logic.

A few points related to AMDP


 AMDP is nothings but a class
 It is always going to be global
 In AMDP class we can write AMDP Methods, AMDP Function Methods, Normal
methods also
 AMDP Methods will allow only pass by value
 We should not use nested structures, tables
 Generic table types will not allow in AMDP
 AMDP method will not allow returning parameter
 AMDP Function Method will not allow Exporting parameter
 Another procedure can call in side AMDP Method or AMDP Function Method. We need
to mention that procedure (class_name=>method_name) in using (method
implementation)
 We should use IF_AMDP_MARKER_HDB interface in the class
 AMDP Method or Function Method should not be empty
 If we create the AMDP class and method, Database Procedure will not save in DB for the
first time. Once we execute the method, then only system will create procedure in DB
 If we want to declare variable by using data element in the AMDP method, this is the
syntax: DECLARE LV_VBTYP "$ABAP.TYPE( vbtypl )";.
 Declarations we can’t write at middle of the method implementation. Those should be at
the beginning of the method implementation.
 Need to maintain client handling by using session_context('CLIENT')

LT_VBAK = SELECT VBELN, AUDAT, VBTYP FROM VBAK where mandt =


session_context('CLIENT');

सतीष कुमार रे ड्डि एम एन Page: 40


AMDP implement from a class
CLASS zamdp_customer DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
TYPES: tt_kna1 TYPE TABLE OF kna1.
INTERFACES: if_amdp_marker_hdb.
METHODS: get_customer
IMPORTING VALUE(imp_kunnr) TYPE kna1-kunnr
EXPORTING VALUE(it_kna1) TYPE tt_kna1.
ENDCLASS.

CLASS zamdp_customer IMPLEMENTATION.


METHOD get_customer BY DATABASE PROCEDURE
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING kna1.
it_kna1 = select * from kna1 where kunnr = :imp_kunnr;
ENDMETHOD.
ENDCLASS.

IF_AMDP_MARKER_HDB is the interface to maintain in class definition without fail. If we


maintain this interface in the class definition then only system will consider it as AMDP.
In the above class, get_customer is the method. We have mentioned one importing and exporting
parameter. For exporting parameters, system will not allow dictionary table or views for
declaring. We need to declare by using local objects. Importing and exporting parameters must
be pass by value.
In class implementation, implemented the method.
METHOD get_customer BY DATABASE PROCEDURE
FOR HDB
Here we are creating one database procedure in DB level by using AMDP. So we need to
mention it.
LANGUAGE SQLSCRIPT
AMDP Script is database dependent. If we are using HANA database, it will allow SQLSCRIPT.
If we are using other DB, we need to mention which script (language) that database will allow.
OPTIONS READ-ONLY

AMDP can read, modify, update the data in the DB level. So we need to mention that we are
reading data or modifying data. If we are modifying, not required to mention this ‘Options’ here.
USING kna1.

We are using KNA1 table in the method implantation. We need to mention all table names or
view names, which are using in the method implementation.

सतीष कुमार रे ड्डि एम एन Page: 41


Note: AMDP will not create Database procedure until we call the method.
REPORT zcustomer_123.
data: lt_kna1 type TABLE of kna1.
parameters: p_kunnr type kunnr.
data(obj_kna1) = new zamdp_customer( ).

obj_kna1->get_customer(
EXPORTING
imp_kunnr = p_kunnr
IMPORTING
it_kna1 = lt_kna1 ).

try.
call METHOD cl_salv_table=>factory
IMPORTING
r_salv_table = data(obj_final)
CHANGING
t_table = lt_kna1 .
CATCH cx_salv_msg.
endtry.

call method obj_final->display( ).

We are calling the AMDP method. Now the database procedure is created in the db.
I’m taking one more example for inner join taking source from another method.
CLASS zamdp_sales DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
INTERFACES: if_amdp_marker_hdb.
types: BEGIN OF ty_vbak,
vbeln type vbak-vbeln,
audat type vbak-audat,
kunnr type kunnr,
end of ty_vbak,
tt_vbak type TABLE of ty_vbak,
lt_vbak1 type TABLE of ty_vbak,
BEGIN OF ty_vbap,
vbeln type vbap-vbeln,
audat type vbak-audat,
kunnr type kunnr,
posnr type vbap-posnr,
matnr type vbap-matnr,
end of ty_vbap,
tt_vbap type table of ty_vbap.
methods: get_vbak IMPORTING VALUE(i_vbeln) type vbak-vbeln EXPORTING VALUE(lt_vbak)
TYPE tt_vbak,
get_vbap IMPORTING VALUE(IMP_VBELN) type VBAK-VBELN EXPORTING VALUE(lt_vbap)
type tt_vbap.
ENDCLASS.

सतीष कुमार रे ड्डि एम एन Page: 42


CLASS zamdp_sales IMPLEMENTATION.
method get_vbak BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
USING vbak.
DECLARE LV_VBTYP "$ABAP.TYPE( vbtypl )";
lt_vbak = select vbeln, audat, kunnr from vbak WHERE VBELN = :I_VBELN;
endmethod.

method get_vbap BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
USING ZAMDP_SALES=>GET_VBAK vbap .
call "ZAMDP_SALES=>GET_VBAK" (I_VBELN => :IMP_VBELN, LT_VBAK => :LT_VBAK1);
lt_vbap = select a.vbeln, a.audat, a.kunnr, b.posnr, b.matnr from :lt_vbak1 as a
inner join vbap as b on
a.vbeln = b.vbeln;
endmethod.
ENDCLASS.

Here get_vbak is the method to fetch data from VBAK table. I’m calling this method in get_vbap
method to get header information and doing inner join.
We are giving invalid input and fetching a single record. Then data will not fetch and it will go to
dump. To avoid this one, we can go thorough like this
select vbtyp into lv_vbtyp1 DEFAULT NULL from vbak ;

Here I’ve mentioned like ‘DEFAULT NULL’. It means, if the data is not fetching from table,
then the value should be null.

DECLARE LV_VBTYP "$ABAP.TYPE( vbtypl )";

We can declare any variable by using ABAP data element as shown in the above syntax.

Union in method implementation


LT_VBAK = SELECT VBELN, AUDAT, VBTYP FROM VBAK where vbtyp = 'A'
union
select vbeln, audat, vbtyp from vbak where vbtyp = 'B';

If we don’t want to fetch some records, we can write the code like this
LT_VBAK = SELECT VBELN, AUDAT, VBTYP FROM VBAK
except
select vbeln, audat, vbtyp from vbak where vbtyp = 'B';

Here, I’ve mentioned like ‘EXCEPT’ means, it will fetch all records from VBAK then it will
remove all the records which record type ‘B’ from the table.

सतीष कुमार रे ड्डि एम एन Page: 43


Clear data from internal table
LT_VBAK = SELECT VBELN, AUDAT, VBTYP FROM VBAK where mandt =
session_context('CLIENT')
except
select vbeln, audat, vbtyp from vbak where vbtyp = 'B';
lv_sales = select * from :lt_vbak;
lt_vbak = select * from :lt_vbak where 1 = 2;

In the above syntax, filling LT_VBAK internal table first. Then passing all the data to
LV_SALES internal table. Then one more time writing select query with false condition. At that
time, whatever the data is available in the internal table, all data will remove.
Otherwise we can write the code as below.
lt_vbak = select null as vbeln, null as audat, null as vbtyp from dummy where
1 = 2;

Select-options in AMDP:
1. Declare Select-options in the program
2. Convert the select-options values into a string
3. Pass the string into procedures using import parameters
4. In Procedure use APPLY_FILTER into the string values which got received
REPORT zp_amdp2.
types: BEGIN OF ty_kna1,
kunnr type kna1-kunnr,
name1 type kna1-name1,
ort01 type kna1-ort01,
end of ty_kna1.
data it_kna1 type table of ty_kna1.
data lv_kunnr1 type kunnr.
select-OPTIONS: s_kunnr for lv_kunnr1.
*Convert s_kunnr to string
data(lv_kunnr) = cl_shdb_seltab=>combine_seltabs(
it_named_seltabs = value #( ( name = 'KUNNR' dref = ref #
( s_kunnr[] ) ) ) ).

zcl_amdp2=>get_data(
EXPORTING
i_kunnr = 'abc'
im_kunnr = lv_kunnr
IMPORTING
et_kna1 = it_kna1[]
).

In the above program I’m just converting select-options into string. Name = ‘KUNNR’ passing
in the IT_NAMED_SELTABS, it means we need to pass the where condition field (it field
should be in the select query and should not provide alias name with different name. for example

सतीष कुमार रे ड्डि एम एन Page: 44


for KUNNR, I can give alias name as ‘Customer’. In this case system will not allow you. Better
to don’t provide any alias name for it otherwise give the alias name as field name only).
CLASS zcl_amdp2 DEFINITION PUBLIC .
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
types: begin of ty_kna1,
kunnr type kna1-kunnr,
name1 type kna1-name1,
ort01 type kna1-ort01,
end of ty_kna1.
types: tt_kna1 type table of ty_kna1.
class-methods get_data IMPORTING VALUE(i_kunnr) type kunnr
value(im_kunnr) type string
EXPORTING VALUE(et_kna1) type tt_kna1.
protected SECTION.
private SECTION.

ENDCLASS.
CLASS zcl_amdp2 IMPLEMENTATION.
method get_data BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY using kna1 .
et_kna1 = select kunnr, name1, ort01 from kna1;
et_kna1 = APPLY_FILTER ( :et_kna1, :im_kunnr );
endmethod.
ENDCLASS.

Imported structure we can pass to APPLY_FILETER statement.


Insert data in database table.
CLASS zcl_amdp_folk3 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
types tt_mard type table of zmard.
interfaces if_amdp_marker_hdb.
class-methods upd_cust EXPORTING VALUE(et_mard) type tt_mard.
ENDCLASS.

CLASS zcl_amdp_folk3 IMPLEMENTATION.


method upd_cust BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT using mard
zmard.
declare et_mard1 table like :et_mard;
declare lv_count int = 0;
declare i int = 0;

lt_mard = select * from mard ;


lv_count = record_count( :lt_mard );

for I in 1..lv_count do
:et_mard1.insert ( ( :lt_mard.mandt[I],
:lt_mard.matnr[I],

सतीष कुमार रे ड्डि एम एन Page: 45


:lt_mard.werks[I],
:lt_mard.lgort[I],
:lt_mard.pstat[I] ), I );
end for;

insert into zmard select * from :et_mard1;


--et_mard1.pstat[1] = 'SJF';
--upsert zmard select * from :et_mard1;
et_mard = select * from :et_mard1;
endmethod.
ENDCLASS.

By using ‘INSERT’ statement, we can insert the data in table.


‘UPSERT’ statement will work in 2 ways.
If the key field record found in the table, then it will modify the data.
If the key field record not found, then it will insert the data in table.

AMDP Function Method can’t execute directly. We need to call this Function method in another
method. We need to execute this method.

AMDP Function Method


CLASS zcl_amdp_testing4 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
types: tt_kna1 type table of kna1 with DEFAULT KEY.
INTERFACES IF_AMDP_MARKER_HDB.
class-methods: get_kna1 EXPORTING VALUE(lt_kna1) TYPE tt_kna1.
class-methods: get_customer IMPORTING VALUE(LV_KUNNR) TYPE KUNNR
returning VALUE(lt_kna1) type tt_kna1.
ENDCLASS.

CLASS zcl_amdp_testing4 IMPLEMENTATION.


method get_customer BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT OPTIONS
READ-ONLY USING kna1.
RETURN select * from kna1;
endmethod.

METHOD GET_KNA1 BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT USING


ZCL_AMDP_TESTING4=>GET_CUSTOMER.
LT_KNA1 = SELECT * FROM "ZCL_AMDP_TESTING4=>GET_CUSTOMER"( LV_KUNNR => '123'
);
ENDMETHOD.
ENDCLASS.

सतीष कुमार रे ड्डि एम एन Page: 46


If we maintain only AMDP Function Method, it will not allow to execute it. Need to take one
more procedure method, from that method, we need to call Function method.

Real time scenario:


For every sales order, check the delivery info.
CLASS zcl_folk3 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
types: BEGIN OF ty_so,
vbeln type vbeln_va,
posnr type posnr_va,
audat type audat,
matnr type matnr,
kwmeng type vbap-kwmeng,
end of ty_so,

BEGIN OF ty_bill,
vbeln type lips-vbeln,
posnr type lips-posnr,
lfdat type likp-lfdat,
lfimg type lips-lfimg,
vgbel type lips-vgbel,
vgpos type lips-vgpos,
end of ty_bill,

BEGIN OF ty_final,
vbeln type vbeln_va,
posnr type posnr_va,
audat type audat,
matnr type matnr,
kwmeng type kwmeng,
bill1 type lips-vbeln,
bill1_dt type audat,
bill1_qty type lips-lfimg,
bill2 type lips-vbeln,
bill2_dt type audat,
bill2_qty type lips-lfimg,
bill3 type lips-vbeln,
bill3_dt type audat,
bill3_qty type lips-lfimg,
tot_bill_qty type lips-lfimg,
pend_qty type lips-lfimg,
end of ty_final.
types: tt_so type table of ty_so,
tt_bill type table of ty_bill,
tt_final type table of ty_final.
class-methods: get_so EXPORTING VALUE(lt_so) type tt_so,
get_bill EXPORTING VALUE(lt_bill) type tt_bill,

सतीष कुमार रे ड्डि एम एन Page: 47


final_rep EXPORTING VALUE(lt_final) type tt_final.
ENDCLASS.

CLASS zcl_folk3 IMPLEMENTATION.


method get_so BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-
ONLY USING vbak vbap.
lt_so = select h.vbeln, i.posnr, h.audat, i.matnr, i.kwmeng from vbak as h
inner join vbap as i
on h.vbeln = i.vbeln where i.kwmeng != 0 and h.mandt =
session_context('CLIENT');
endmethod.

method get_bill BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS


READ-ONLY USING likp lips.
lt_bill = select h.vbeln, i.posnr, h.lfdat, i.lfimg, i.vgbel, i.vgpos from
likp as h inner join lips as i
on h.vbeln = i.vbeln and h.mandt = session_context('CLIENT');
endmethod.

method final_rep BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS


READ-ONLY USING ZCL_FOLK3=>GET_SO ZCL_FOLK3=>GET_BILL.
DECLARE LV_SO_REC INT = 0; -- SO Count
DECLARE LV_BILL_REC INT = 0; -- No of billing records
DECLARE I INT = 0;
DECLARE M INT = 0;
DECLARE LV_VBELN NVARCHAR( 10 );
DECLARE LV_POSNR "$ABAP.TYPE( POSNR_VA )";
DECLARE SUB_BILL_QTY "$ABAP.TYPE( LFIMG )" = 0;

-- Get SO info
call "ZCL_FOLK3=>GET_SO"( LT_SO => :LT_SO1 );
LV_SO_REC = RECORD_COUNT( :LT_SO1 ); -- No of records in LT_SO1

-- Get Billing info


CALL "ZCL_FOLK3=>GET_BILL"( LT_BILL => :LT_BILL1);

FOR I IN 1..LV_SO_REC DO -- Loop LT_SO1


LT_FINAL.VBELN[ I ] = :LT_SO1.VBELN[ I ];
LT_FINAL.POSNR[ I ] = :LT_SO1.POSNR[ I ];
LT_FINAL.AUDAT[ I ] = :LT_SO1.AUDAT[ I ];
LT_FINAL.MATNR[ I ] = :LT_SO1.MATNR[ I ];
LT_FINAL.KWMENG[ I ] = :LT_SO1.KWMENG[ I ];

LV_VBELN = :LT_SO1.VBELN[ I ];
LV_POSNR = :LT_SO1.POSNR[ I ];

LT_TEMP_BILL = SELECT VBELN, POSNR, LFDAT, LFIMG, VGBEL, VGPOS FROM :LT_BILL1
WHERE VGBEL =
LV_VBELN
AND VGPOS =
LV_POSNR;
if is_empty( :lt_temp_bill ) then

else

सतीष कुमार रे ड्डि एम एन Page: 48


LV_BILL_REC = RECORD_COUNT( :LT_TEMP_BILL ); -- Get number reocords in
:LT_TEMP_BILL

FOR M IN 1..LV_BILL_REC DO -- Loop Billing info


IF( M = 1 ) THEN
LT_FINAL.BILL1[ I ] = :LT_TEMP_BILL.VBELN[ M ];
LT_FINAL.BILL1_DT[ I ] = :LT_TEMP_BILL.LFDAT[ M ];
LT_FINAL.BILL1_QTY[ I ] = :LT_TEMP_BILL.LFIMG[ M ];

SUB_BILL_QTY = :SUB_BILL_QTY + :LT_TEMP_BILL.LFIMG[ M ];

ELSEIF( M = 2 ) THEN
LT_FINAL.BILL2[ I ] = :LT_TEMP_BILL.VBELN[ M ];
LT_FINAL.BILL2_DT[ I ] = :LT_TEMP_BILL.LFDAT[ M ];
LT_FINAL.BILL2_QTY[ I ] = :LT_TEMP_BILL.LFIMG[ M ];
SUB_BILL_QTY = :SUB_BILL_QTY + :LT_TEMP_BILL.LFIMG[ M ];

ELSEIF( M = 3 ) THEN
LT_FINAL.BILL3[ I ] = :LT_TEMP_BILL.VBELN[ M ];
LT_FINAL.BILL3_DT[ I ] = :LT_TEMP_BILL.LFDAT[ M ];
LT_FINAL.BILL3_QTY[ I ] = :LT_TEMP_BILL.LFIMG[ M ];
SUB_BILL_QTY = :SUB_BILL_QTY + :LT_TEMP_BILL.LFIMG[ M ];
END IF;

END FOR;
LT_FINAL.TOT_BILL_QTY[ I ] = SUB_BILL_QTY;
LT_FINAL.PEND_QTY[ I ] = ( :LT_SO1.KWMENG[ I ] - SUB_BILL_QTY );
sub_bill_qty = 0;
end if;
END FOR;

endmethod.

ENDCLASS.

AMDP Method for other schema database table


Current Application layer (ABAP layer) schema is

Click on system  status. We can get above screen and we can see default schema name.

सतीष कुमार रे ड्डि एम एन Page: 49


If we want to fetch data from another schema, we can write the logic like this.
CLASS zcl_aoh2_amdp8 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
TYPES: BEGIN OF TY_SO,
VBELN TYPE VBELN_VA,
KUNNR TYPE KUNNR,
VBTYP TYPE VBTYP,
END OF TY_SO.

TYPES TT_SO TYPE TABLE OF TY_SO.


INTERFACES IF_AMDP_MARKER_HDB.
CLASS-METHODS GET_DATA EXPORTING VALUE(LT_SO) TYPE TT_SO.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.

CLASS zcl_aoh2_amdp8 IMPLEMENTATION.


METHOD get_data BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS
READ-ONLY.
LT_SO = SELECT * FROM "ABAPHANA1"."ZSO";
ENDMETHOD.
ENDCLASS.

सतीष कुमार रे ड्डि एम एन Page: 50


What is CDS View?
CDS View is semantically rich data model. CDS is enhancement of SQL.
In SQL, we can get DDL, DCL, TCL (DML will not support by CDS). Enhancement of SQL
means, we need to add a few extra functionalities or properties to the SQL like adding
Annotations, Associations, Path expressions
Annotations: CDS view will provide something data. Apart from that data, for more information
of that data & enabling some concepts like allow the data to another component – Odata Service,
Analytics then we will go for Annotations.

Limitations of ABAP dictionary views


 It supports only inner join
 Calculation expression, aggregation, grouping not supported
 Nested views not supported
SAP introduced CDS views to fulfill code to data option.
With CDS Views, data models are defined, consumed in database server and application server.
CDS is an enhancement of SQL which provides you with DDL for defining semantically rich
table, views & user defined types in database.
CDS views are a collection of domain specific languages & services for defining & consuming
semantically rich data models. CDS views are made of with 3 sub languages. DDL, DCL, QL
Difference between ABAP CDS & HANA CDS
ABAP CDS HANA CDS
Support all databases Supports only HANA database
Located on the application server Located on the SAP HANA DB directly
Access to support the implementation of Supports the development of SAP HANA
ABAP applications independent of database Native application (SAP HANA XS)
system

Note: ABAP CDS view will support read data only & not for modify or write data.
Difference between ABAP dictionary view & CDS
ABAP Dictionary View CDS View
Support on all DBMS Yes Yes
Support combining queries Inner join Inner, outer, union
Calculation No Yes
Nested view No Yes

There is no editor for DDL source code in classical ABAP work bench. That is why the new type
of repository object can be analyzed and developed in ADT (ABAP Development Tool). After

सतीष कुमार रे ड्डि एम एन Page: 51


activation of DDL source code, two objects will create. SQL view and CDS view. SQL view is
visible as an object in ABAP dictionary. We can’t edit it in ABAP dictionary. We can use to read
data in fraction of seconds. CDS view carries more semantics information than SQL view. It can
be consume via New Open SQL & CDS view don’t required explicit client handling.
Annotations will allow ABAP additional specific information.

Syntax rules inside DDL source:


 Keywords must be all upper case or all lower case or in lower case with an upper case
initial letter. Mixed upper & lower case is not possible.
 Two forward lines (//) introduce a comment which contains until end of the line. For
multiple lines comment we have to do like this
/*
Select Field1, Field2
from DB_TABLE
*/
 Names are not case sensitive & maximum 30 characters
 Allowed 1, 2.5, 0.5 but not .5
 DDL source name we can take up to 30 characters & all are in upper case
 CDS view name we can take up to 30 characters and not case sensitive & differ from
DDL source name.
 SQL view name we can take up to16 characters & it is not case sensitive & it should
different from CDS view name.

How to create CDS Views:-


Open ABAP perspective in HANA studio / Eclipse If you want to create CDS view in your
own package, expand your package or expand Local Object folder as shown in below image.

Right click on your user id  New  Other ABAP Repository Object  Expand Code Data
Services  Select Data Definition  Click on Next Button  Provide the Package name, CDS
view name, Description.

सतीष कुमार रे ड्डि एम एन Page: 52


If you have any specific package, then provide that package otherwise you can provide $TMP
(Local Object). Click on Next button. If you have selected any specific package, then you have
select the Transport Request Number otherwise the screen will be in disable mode. Click on Next
button.

सतीष कुमार रे ड्डि एम एन Page: 53


Select one template, click on Finish button.
@AbapCatalog.sqlViewName: 'ZSQL_DDL_EX1'
@EndUserText.label: 'Example CDS View'
define view ZCDS_DDL_EX1 as select from scarr {
carrid as airline_id,
carrname as airline_name,
currcode as currency,
url as website
}

Here, @AbapCatalog.sqlViewName annotation is mandatory. Without this one, we can’t activate


the CDS view.

For checking the code, shortcut is Ctrl + F2, for activating the view shortcut is Ctrl + F3, for
executing the view the shortcut is F8. You can see the shortcut buttons in the above image.

After execute the CDS view, it will display in this format. You can add filters, you can restrict
maximum number records to display and you can get to know how many records displayed. If
you want to know the background SQL syntax for the displaying the output, you can click on
SQL Console.
If you want to open the SQL View in SAP GUI, Select the SQL View name, click on F3 button.
It will navigate to SAP GUI. But you can’t edit SQL view in SAP GUI.
If you want to know that CDS view is used in any object or not (Where used list in SAP GUI),
select the CDS view in the left panel, Right click on it  Open with  Dependency Analyzer.

सतीष कुमार रे ड्डि एम एन Page: 54


Now you can create CDS view. If you want to get to know that how the view is creating in
background, Right click on the free space in the CDS view  Show SQL CREATE Statement.

It will show the create statement in SQL.

Note: CDS is a just view as DDIC view. By using CDS, we can add some extra features. If we
want to save this CDS view in DB layer, then we need to use the below annotation.
@AbapCatalog.sqlViewName:
By using the above annotation, we can save the CDS view in Database layer. Off course this is
mandatory annotation for every CDS view, otherwise system will through error.
By using @EndUserText.label annotation, we can display the description in ABAP Layer,
otherwise it will display the standard description.

Note: By default, CDS view is client dependent. If you want to make it as client independent,
then you have to pass one annotation as @clientdependent: false

Consume CDS view in Application server:


@AbapCatalog.sqlViewName: 'ZSQL_PO'
define view zpo as select from ekko as h inner join ekpo as p on h.ebeln =
p.ebeln {
key h.ebeln,
key p.ebelp,
p.matnr
}

सतीष कुमार रे ड्डि एम एन Page: 55


Created the above CDS view and using it in ABAP program.
SELECT * FROM zpo INTO TABLE @DATA(lt_po).
cl_demo_output=>display(
EXPORTING
data = lt_po ).

CDS View with alias Field names:


@AbapCatalog.sqlViewName: 'ZSQL_PO'
define view zpo as select from ekko as h inner join ekpo as p on h.ebeln =
p.ebeln {
key h.ebeln as po_number,
key p.ebelp as PO_item,
p.matnr as material
}

In the output we can see the alias names instead of technical names.

If we want display the space in between of two words in field names, we can go for annotations.

CDS view with ‘where’ condition:


@AbapCatalog.sqlViewName: 'ZSQL_PO'
define view zpo as select from ekko as h inner join ekpo as p on h.ebeln =
p.ebeln {
key h.ebeln as po_number,
key p.ebelp as PO_item,
p.matnr as material
}
where h.bsart = 'NB'

CDS view with input parameter:


@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX5'
@EndUserText.label: 'parameters'
define view ZCDS_DDL_EX5
with parameters
p_date : audat,
p_netwr : abap.curr(15,2)
as select from vbak
{
key vbeln,
audat,
kunnr
}
where
audat = $parameters.p_date

सतीष कुमार रे ड्डि एम एन Page: 56


and netwr = :p_netwr
I’m declaring the parameters in two ways. By using data element and direct data type and length.
If we want to apply parameter in where condition, we can apply in two ways
$parameters.PARAMETER_NAME (system can get to know that we are using input parameter)
:PARAMETER_NAME (system can get to know that we are using local variable)
We can use any method for parameter.
parameters p_dodt type vbak-audat.
parameters p_nval type vbak-netwr.
select * from ZCDS_SO( p_date = @p_dodt, p_netwr = @p_nval ) into TABLE
@data(lt_final).
cl_demo_output=>display(
EXPORTING
data = lt_final ).

We can use the parameterized CDS view in ABAP program as above.

Note: If we have parameters in CDS view, we can display it in SE11 but can’t execute (can’t
display the output).

CDS View with CASE expression


Instead of Nested if concept we can go for case statement for performance increase.
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX2'
@EndUserText.label: 'Example on Flight Info'
define view ZCDS_DDL_EX2 as select from vbak {
vbeln as SO_num,
vbtyp as type,
audat as doc_date,
netwr as net_amt,
case vbtyp
when 'A' then 'Inquiry'
when 'B' then 'Quotation'
when 'C' then 'Order'
else 'Others'
end as doc_type,
//netwr * 0.30 as new_amt1,
cast (netwr as abap.fltp) * 0.30 as new_amt,
concat(vbtyp, vbeln) as doc_num
}

If we are doing any calculation, input fields and output fields must and should be same data type.
So, need to convert it to float data type. For that we need to apply like this
cast (netwr as abap.fltp) * 0.30 as new_amt

सतीष कुमार रे ड्डि एम एन Page: 57


CDS view with select-options
@AbapCatalog.sqlViewName: 'ZSQL_MAT_INFO'
define view zcds_mat_info
with parameters low_matnr : matnr,
high_matnr : abap.char(40)
as select from mara {
key matnr,
mtart
}
where matnr between $parameters.low_matnr and $parameters.high_matnr

Directly select-options will not work in CDS views. Instead of that one, we can apply only one
range as select-options by using between operator.

CDS view with system fields


@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX13'
define view ZCDS_DDL_EX13 as select from vbak {
key vbeln,
audat,
$session.client as clint,
$session.system_language as language,
$session.user as curr_user,
$session.system_date as sys_date
}

If you want to use system fields, then we have to write like this $session.client (if we click on
Ctrl + space after $session, it will display all system fields)

CDS View with Joins (Inner, Left Outer, Right Outer)


@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX4'
@EndUserText.label: 'Joins, Union & Union All'
define view ZCDS_DDL_EX4 as select from vbak as k
left outer join vbap as p
on k.vbeln = p.vbeln {
k.vbeln,
k.audat,
k.kunnr,
p.posnr,
p.matnr,
p.kwmeng,
p.netwr
}
If we want Right outer join or Left out join, we can use in CDS view.
CDS view with Cross Join
I’m creating two tables here.

सतीष कुमार रे ड्डि एम एन Page: 58


I’m creating Cross join on top of the above two tables.
@AbapCatalog.sqlViewName: 'ZSQL_EMP'
define view zcds_emp as select from zemp_head as h
cross join zemp_allowance as a {
h.emp_no as employee_number,
h.emp_name as employee_name,
a.allowance_name as allowance_name,
a.percent as allowance_Percentage
}

Output will come like this.


For one record in left hand side table it will pick all records from right hand side table. This is
Cross Join.

CDS View with Union & Union all


@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX4'
@EndUserText.label: 'Joins, Union & Union All'
define view ZCDS_DDL_EX4
as select from vbak
{
vbeln
}
where
vbeln = '0000000002'

union all select from vbap


{
vbeln
}

सतीष कुमार रे ड्डि एम एन Page: 59


where
vbeln = '0000000002'

I’ve used Union all here. The output will come like this.

In VBAK one record is available and in VBAP two records are available. By using Union all
total records are coming as 3 in the output. Here it will not delete the duplicate records. If we use
Union then in output only one record will come.

If we use Union then it will remove the duplicate entries. That is the difference between union
and union all.

Consume CDS View in another CDS view


@AbapCatalog.sqlViewName: 'ZSQL_MAT_DET'
define view zcds_mat_det as select from zcds_mat_info( p_matnr : 'EWMS4-02')
as m
inner join makt as k on m.matnr = k.matnr {
//zcds_mat_info
key m.matnr,
mtart,
k.maktx
}
where k.spras = $session.system_language
Here ZCDS_MAT_INFO is one CDS view. I’m using this in another CDS view.

Associations
Association are three types. 1.Ad-hoc, 2.Exposed 3.Filtered Association
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX7'
@EndUserText.label: 'Associations'
define view ZCDS_DDL_EX7 as select from vbak as k association to vbap as p
on k.vbeln = p.vbeln
{
k.vbeln,
k.audat,
k.kunnr,
p.posnr, //ad-hoc association
p.matnr //ad-hoc association
}

सतीष कुमार रे ड्डि एम एन Page: 60


If we check the SQL code (Right click on the code  Show SQL CREATE Statement) for the
above view, it will display like this.
CREATE OR REPLACE VIEW "ZCDS_SQL_EX7" AS SELECT
"K"."MANDT" AS "MANDT",
"K"."VBELN",
"K"."AUDAT",
"K"."KUNNR",
"=A0"."POSNR",
"=A0"."MATNR"
FROM "VBAK" "K" LEFT OUTER MANY TO ONE JOIN "VBAP" "=A0" ON (
"K"."MANDT" = "=A0"."MANDT" AND
"K"."VBELN" = "=A0"."VBELN"
)
Immediately it is creating join in background.
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX7'
@EndUserText.label: 'Associations'
define view ZCDS_DDL_EX7
as select from vbak as k
association to vbap as p on k.vbeln = p.vbeln
{
Key k.vbeln,
k.audat,
k.kunnr,
P //Exposed Association
}

I’m using the above code for Exposed association. If we check SQL code for this one,
CREATE OR REPLACE VIEW "ZCDS_SQL_EX7" AS SELECT
"K"."MANDT" AS "MANDT",
"K"."VBELN",
"K"."AUDAT",
"K"."KUNNR"
FROM "VBAK" "K"
It is not creating any join here. If we execute this view, it will display only VBAK table fields (3
fields).
If we want to display VBAP table information for particularly one record, Right click on the
record in the output.

सतीष कुमार रे ड्डि एम एन Page: 61


Click on Follow Association.

Select the cardinality.


Now we can see the output.
Note: In CDS view, we have to mention key fields otherwise the above concept will not work. If
we click on cardinality, it will display all records from VBAP table.
If we want to fetch a few fields from VBAP table, we can use the above view in another CDS
view like below program.
Previous CDS View name: ZCDS_SQL_EX7.
Current CDS View Name: ZCDS_SQL_EX8.
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX8'
@EndUserText.label: 'Exposed CDS View'
define view ZCDS_DDL_EX8
as select from ZCDS_DDL_EX7 as a
{
key vbeln,
a.audat,
a.kunnr,
a.p.posnr,
a.p.matnr
}

Here, I’m adding fields from VBAP table. If we check the SQL code,
CREATE OR REPLACE VIEW "ZCDS_SQL_EX8" AS SELECT
"A"."MANDT" AS "MANDT",
"A"."VBELN",
"A"."AUDAT",

सतीष कुमार रे ड्डि एम एन Page: 62


"A"."KUNNR",
"=A0"."POSNR",
"=A0"."MATNR"
FROM "ZCDS_SQL_EX7" "A" LEFT OUTER MANY TO ONE JOIN "VBAP" "=A0" ON (
"A"."MANDT" = "=A0"."MANDT" AND
"A"."VBELN" = "=A0"."VBELN"
)

Note: If we are using associations, we have to note one point. We have to mention all fields in
the select statement which are mentioned in the ON Condition.

Note: By default, Association will apply Left Outer Join. We can change it to other joins as
below CDS view.
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX16'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Associations'
define view ZCDS_DDL_EX16
as select from vbak as k
association to vbap as p on k.vbeln = p.vbeln
{
key k.vbeln,
k.audat,
p[inner].matnr
}

We can check the SQL code which is generated in backend.


CREATE OR REPLACE VIEW "ZCDS_SQL_EX16" AS SELECT
"K"."MANDT" AS "MANDT",
"K"."VBELN",
"K"."AUDAT",
"=A0"."MATNR"
FROM "VBAK" "K" INNER JOIN "VBAP" "=A0" ON (
"K"."MANDT" = "=A0"."MANDT" AND
"K"."VBELN" = "=A0"."VBELN"
)
Here we can see that inner join applied here.

Note: If we are using associations, we are selecting common fields, then need not to mention
alias_name.field_name. Automatically it will pick the value from left side table. If we are
selecting other than common fields from right side table, then we need to mention
alias_name.fieldname. For left side tables, not required to mention alias_name.fieldname.

सतीष कुमार रे ड्डि एम एन Page: 63


Call Association fields in a program in SE38
@AbapCatalog.sqlViewName: 'ZSQL_SO'
define view zcds_so as select from vbak as _sheader
association [1..*] to vbap as _sitem
on _sheader.vbeln = _sitem.vbeln
{
key _sheader.vbeln as so_number,
_sheader.kunnr as customer,
_sheader.vbtyp as document_type,
_sitem
}

In the above CDS View, I’ve mentioned _sitem (it’s public). In SE38 (ABAP editor), I’m
selecting the fields like this from _sitem.
select so_number,
customer,
document_type,
\_sitem-posnr as so_item,
\_sitem-matnr as material
from zcds_so
into TABLE @data(lt_so).

cl_demo_output=>display(
EXPORTING
data = lt_so
).

Here, I’ve mentioned ‘from ZCDS_SO’ If we take SQL view (SE11 view), it will throw error. If
we are not taking fields from _sitem , then it will not throw any error. We are selecting some
fields from _sitem and we need to avoid error. In this case we should use DDL view (CDS View
name which has given in Hana Studio / Eclipse).

Path Expression
@AbapCatalog.sqlViewName: 'ZSQL_SO'
define view zcds_so as select from vbak as _sheader
association [1..*] to vbap as _sitem on _sheader.vbeln = _sitem.vbeln
association [1..1] to kna1 as _customer on _sheader.kunnr = _customer.kunnr
{
key _sheader.vbeln as so_number,
_sheader.kunnr as customer,
_sheader.vbtyp as document_type,
_sitem,
_customer.name1 as CUSTOMER_NAME
}

I’ll use this CDS view in different CDS view.


@AbapCatalog.sqlViewName: 'ZSQL_SO1'
define view zcds_so1 as select from zcds_so
{
//ZCDS_SO

सतीष कुमार रे ड्डि एम एन Page: 64


key so_number,
customer,
document_type,
CUSTOMER_NAME,
/* Associations */
//ZCDS_SO
_sitem
}

Output will come like this.

I want to display customer name(should not disturb other field values) for only a specific
customer number (here I’m considering 0017100001). Then we can apply path expression.
I’m just doing some modification here for the first CDS view.
@AbapCatalog.sqlViewName: 'ZSQL_SO'
define view zcds_so as select from vbak as _sheader
association [1..*] to vbap as _sitem on _sheader.vbeln = _sitem.vbeln
association [1..1] to kna1 as _customer on _sheader.kunnr = _customer.kunnr
{
key _sheader.vbeln as so_number,
_sheader.kunnr as customer,
_sheader.vbtyp as document_type,
_sitem,
_customer
}

In second CDS view I’m using path expression like this.


@AbapCatalog.sqlViewName: 'ZSQL_SO1'
define view zcds_so1 as select from zcds_so
{
//zcds_so
key so_number,
customer,
document_type,

सतीष कुमार रे ड्डि एम एन Page: 65


/* Associations */
//zcds_so
_customer[kunnr = '0017100001'].name1 as customer_name,
_sitem
}

Aggregate Functions
@AbapCatalog.sqlViewName: 'ZSQL_AGGR_FUN'
define view zcds_aggr_fun as select from vbap {
key vbeln,
sum( netwr ) as sum_netwr,
min( netwr ) as min_netwr,
max( netwr ) as max_newr,
avg( netwr ) as avg_newr,
count(*) as count_num
} group by vbeln

If we are using Sum or min or max or avg or count any aggregate function then we must take
group by with non-aggregate function fields.
@AbapCatalog.sqlViewName: 'ZSQL_AGGR_FUN'
define view zcds_aggr_fun as select from vbap {
count(*) as num,
count(distinct vbeln ) as count_num
} where vbeln = '0000000165'
and matnr = '000000000000000140'

In Count(*) we can see the duplicates but in count(distinct <field_name>) duplicates will
remove.
@AbapCatalog.sqlViewName: 'ZSQL_HAVING'
define view ZCDS_having as select from kna1 as c inner join vbak as h on
c.kunnr = h.kunnr {
key c.kunnr as customer,
count(distinct h.vbeln) as count_so,
sum(h.netwr) as sum_amt
}group by c.kunnr
having sum(h.netwr) >= 2250000.00

सतीष कुमार रे ड्डि एम एन Page: 66


Here I’m using ‘Having’ instead of ‘Where’ condition. If we use ‘Where’ condition, we can’t
apply aggregate function in ‘where’ condition and if we consider ‘Where’ condition, it will
check every record from VBAK table which is grater than the ‘where’ condition value. My
requirement is after getting sum up, I need to filter it. In this case we can go for ‘Having’.

Extend View

Extend view is nothing but enhancement. If we want to add any field in standard or custom CDS
view without disturbing the view, we can go for Extend View.

Here I’m taking one CDS View name as ZCDS_DDL_EX2. In the 3rd line, we can see square
symbol. That symbol indicates that, this is enhanced with another view. If we open it in ABAP
Workbench, enhanced fields will add by using APPEND structure.

I’ve applied the extend view like this.


@AbapCatalog.sqlViewAppendName: 'ZCDS_SQL_EX10'

सतीष कुमार रे ड्डि एम एन Page: 67


@EndUserText.label: 'Extend View'
extend view ZCDS_DDL_EX2 with ZCDS_DDL_EX10
association to vbap as P on vbak.vbeln = P.vbeln
{
kunnr as CUSTOMER,
P.posnr,
P.matnr
}

We can add associations, concatenates in the Extend View. Joins will not support in the Extend
View.
I’ll take one more example.
@AbapCatalog.sqlViewName: 'ZS_AGR_FUN2'
@EndUserText.label: 'aggreage functions'
define view zc_agr_fun2 as select from vbap {
vbeln,
count(*) as count_vbeln,
sum(netwr)as sum_netwr
} group by vbeln

I’m just maintain aggregate functions in CDS view. Now I’ll create one extension view for the
above view.

System is not allowing to add extension view for the view which has implemented with
aggregate functions.
By adding one annotation we can overcome in this issue.
@AbapCatalog.sqlViewName: 'ZS_AGR_FUN2'
@EndUserText.label: 'aggreage functions'
@AbapCatalog.viewEnhancementCategory: [ #PROJECTION_LIST, #GROUP_BY]
define view zc_agr_fun2 as select from vbap {
vbeln,
count(*) as count_vbeln,
sum(netwr)as sum_netwr
} group by vbeln

Here I’ve used one annotation @AbapCatalog.viewEnhancementCategory: [


#PROJECTION_LIST, #GROUP_BY] .
After using this annotation, it will allow the extension view even though we have applied
aggregate functions.

सतीष कुमार रे ड्डि एम एन Page: 68


If we have used union in one CDS view and creating one extension view for it. Then we have to
maintain one annotation like this.
@AbapCatalog.viewEnhancementCategory: [ #PROJECTION_LIST, #UNION ]

SQL Functions:
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX20'
@EndUserText.label: 'inbuilt functions'
define view zsql_fun2 as select from vbak {
netwr as net_price,
ceil(10.2) as ceil_netwr,
floor(20.9) as floor_netwr,
abs(-200) as abs_val,
div(9,2) as div_val,
round(netwr,0) as round_num,
division(10,3,2) as division_num,
mod(9,2) as mod_val,
cast(vbeln as char30) as cast_vbeln
}

Ceil will take lowest nearest value, Floor will consider highest nearest value.
ABS will remove negative symbols.
Round will nearest low or high value (low will consider for <.4 value. High will conider for >=.5
value).
Div display only numeric value not float value.
Division will consider floating value depend given digits.
Mod will work like numeric only.

@AbapCatalog.sqlViewName: 'ZSQL_AF_FUN'
define view zcds_ag_fun as select from kna1 {
kunnr,
name1,
ort01,
land1,
// Length
length(name1) as len_name,
// Concatenate two fields
concat(land1, ort01) as con_name,
// Concatenate two fields with space
concat_with_space(land1, ort01, 1) as con_name_sp,
// Nested Concatenate
concat_with_space(concat_with_space(land1, '-', 1), ort01, 1) as
nest_con,
// Ltrim
ltrim(kunnr,'0') as ltrim_kunnr,
// Rtrim
rtrim('123.00', '0') as rtrim_num,
// Nested Rtrim
rtrim(rtrim('123.00', '0'), '.') as nest_rtrim
}

सतीष कुमार रे ड्डि एम एन Page: 69


Length means it will display the total number of characters that field contain
Concat will concatenate two fields
Concat_with_space will concatenate two fields with space (need to provide how much length of
space (2 spaces or 3 spaces like that) required.
Ltrim will remove the mentioned letter/number from left side
Rtrim will remove the mentioned letter/number from right side.

@AbapCatalog.sqlViewName: 'ZSQL_FUN1'
define view zcds_sql_fun1 as select from kna1 {
kunnr,
name1,
land1,
upper(name1) as upper_name,
lower(name1) as lower_name,
left(name1,5) as left_name,
right(name1,5) as right_name,
lpad(land1, 20, 'INDIA - ') as lpad_land1,
rpad(land1, 20, 'IN - ') as rpad_land1
}

Upper will convert the field value in upper case


Lower will convert the field value in lower case
Left will consider mentioned number of characters from that source field (from left side)
Right will consider mentioned number of characters from that source field (from right side)
Lpad will add the given value. Need to provide the length also for that field. If something space
is there it repeat the same characters once again.
For example customer name is ‘SJF’. I’m using lpad( name, 10, ‘ind’).
Here I’m telling to the system that take 10 characters length and add ‘ind’ that field from left
side. So the name will come like indsjf. Total number of characters is 6. It will repeat once more
time to add ‘ind’. It will come like indindsjf. Now the total length is 9. One more time it will
repeat, it will come like indindisjf. It will consider only 10 characters. That is why it will come
like this.
Rpad is reverse to Lpad means, it will add characters from right side.

@AbapCatalog.sqlViewName: 'ZSQL_SPL_FUN'

सतीष कुमार रे ड्डि एम एन Page: 70


define view zcds_spl_fun1 as select from demo_expressions {
fltp1,
// cast(netwr as abap.dec( 10, 2 )) as cast_fltp_dec
fltp_to_dec(fltp1 as abap.dec( 10, 2 )) as fltp_to_dec_num,
fltp_to_dec(fltp1 as abap.curr( 10, 2 )) as fltp_to_curr_num,
fltp_to_dec(fltp1 as abap.quan( 10, 3 )) as fltp_to_quan_num
}

If we want to convert float value to decimal by using CAST, it will not support. We can convert
it by using FLTP_TO_DEC. We can convert to currency, quantity also by using this.
@AbapCatalog.sqlViewName: 'ZSQL_FUN30'
define view zsql_fun3 as select from mara {
matnr,
ntgew,
gewei,
unit_conversion( quantity => ntgew,
source_unit => gewei,
target_unit => cast('G' as abap.unit( 3 ))) as unit_conv
} where ntgew <> 0

If we want to convert unit of measurement (KM-M, KG-G etc), we can go for


UNIT_CONVERSION.
@AbapCatalog.sqlViewName: 'ZSQL_FUN31'
define view ZCDS_SQL_FUN3 as select from vbap {
netwr,
currency_conversion( amount => netwr,
source_currency => cast('USD' as abap.cuky( 5 )),
target_currency => cast('INR' as abap.cuky( 5 )),
exchange_rate_date => cast('20220126' as abap.dats )
--exchange_rate_date => cast($session.system_date as abap.dats ) )
) as curr_conv
}

If we want to convert one currency to another currency, we can use above query.
@AbapCatalog.sqlViewName: 'ZSQL_FUN4'
define view zcds_sql_fun4 as select from vbak {
vbeln,
erdat,
dats_days_between(cast('20220101' as abap.dats), cast('20220112' as
abap.dats)) as day_between,
dats_days_between(erdat, audat) as days_between,
dats_add_days(erdat, 30, 'INITIAL') as days_add,
dats_add_months(erdat, 4, 'INITIAL') as months_add
}

We can find out number of days in between of two days, can add number of days to a particular
day, can add months to a particular day as shown in the above CDS View.

सतीष कुमार रे ड्डि एम एन Page: 71


Annotations
@EndUserText.label: 'Material Type'

@AbapCatalog.sqlViewName: 'ZSQL_MAT_DET'
define view zcds_mat_det as select from mara {
key matnr as material,
@EndUserText.label: 'Material Type'
@EndUserText.quickInfo: 'Type of Material'
mtart as material_type
}

If the user wants to display the heading of the field with out under square ( _ ), then we can go
for @EndUser.Text.label
We can see the output in a program. In CDS view execute we can’t see the output like this.
Create a program in SE38 transaction with below code and execute.
cl_salv_gui_table_ida=>create_for_cds_view( 'ZCDS_MAT_DET' )->fullscreen( )-
>display( ).

We can’t see the heading in CDS view but we can see it in ABAP program output as shown in
above image.

Preserve Key : @AbapCatalog.preserveKey: true

@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX13'
@AbapCatalog.preserveKey: true
define view ZCDS_DDL_EX13 as select from vbak {
key vbeln,
audat,
$session.client as clint,
$session.system_language as language,
$session.user as curr_user,
$session.system_date as sys_date
}

If we give ‘key’ prefix to the field in the view (non-key fields from table also) system will
consider as key field. We can check it in SE11 view by using SQL View name.
If we are not using this annotation or if we are passing the value as ‘False’, Then system will
consider key fields as in table (if I give ‘key’ to the non-key field and I’m not using the
annotation, then system will not consider it as key field. You can check in SE11 view).

सतीष कुमार रे ड्डि एम एन Page: 72


Buffering

@AbapCatalog.buffering.status: #SWITCHED_OFF / #ACTIVE / #NOT_ALLOWED


@AbapCatalog.buffering.type: #NONE / # GENERIC / #FULL / #SINGLE
@AbapCatalog.buffering. numberOfKeyFields: 000

Actually we can write the above buffering annotations as below.


@AbapCatalog: {
buffering: {
status: #SWITCHED_OFF / #ACTIVE / #NOT_ALLOWED ,
type: #NONE / # GENERIC / #FULL / #SINGLE ,
numberOfKeyFields: 000
} )

When we are creating data base table (SE11), we can give buffering options like this in technical
settings.

Same options we can give in CDS view also.


status: #SWITCHED_OFF / #ACTIVE / #NOT_ALLOWED

#ACTIVE: Buffering activated in this CDS View


#NOT_ALLOWED: Buffering not activated in CDS View
#SWITCHED_OFFF: Buffering allowed but as of now it is switched off

type: #NONE / # GENERIC / #FULL / #SINGLE ,


#NONE: Don’t consider any record in buffer

#SINGLE: Selected non-key fields will go to buffer


#GENERIC: Selected key fields will go to buffer
#FULL: All records will go to buffer from this CDS view
numberOfKeyFields: How many records we can add in buffer area.

सतीष कुमार रे ड्डि एम एन Page: 73


Prerequisite to apply Buffer in CDS View
This view should not contain any another CDS View / Database Dictionary Views
Input parameters we should not apply in CDS View (If we use buffer annotation)

Database Specific Annotation

@AbapCatalog.dbHints: [{
dbSystem: #HDB / #DB2 / #DB6 / #ORA ,
hint: ''
}]

CDS View can create on top of any database for example HANA (HDB), DB2, DB4, DB, Oracle
(ORA), etc. Just we are telling to the system that, which database we are using as of now and just
giving something hint for it.

Enhancement category:

@AbapCatalog.viewEnhancementCategory: [ #PROJECTION_LIST, #GROUP_BY, #UNION]


If we want to extend vied on top of one CDS view (parent view), and we are using aggregate
function or union in CDS view(parent), then we need to mention this annotation.
If we are using aggregate functions, we need to mention like this
@AbapCatalog.viewEnhancementCategory: [ #PROJECTION_LIST, #GROUP_BY]

If we are using union, we need to mention like this


@AbapCatalog.viewEnhancementCategory: [ #PROJECTION_LIST, #UNION]

Here #PROJECTION_LIST is nothing but allow a few more fields from extend view.

Client Handling : @ClientHandling.type: #INHERITED

@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX14'
@ClientHandling.type: #INHERITED
define view ZCDS_DDL_EX14 as select from zvbak1 inner join vbap
on zvbak1.vbeln = vbap.vbeln {
key vbap.vbeln,
audat,
vbap.posnr,
vbap.matnr
}

In the above view, I’ve used one more extra annotation @ClientHandling.type: #INHERITED
By default CDS View is Client Dependent. Not required to add this annotation externally as
@ClientHandling.type: #CLIENT_DEPENDENT. If we use this annotation as
#CLIENT_DEPENDENT there is no issue.

सतीष कुमार रे ड्डि एम एन Page: 74


If we pass the value as #CLIENT_INDEPENDENT for a view which is client dependent table, it will
through error. If we pass the value #CLIENT_DEPENDENT to the client independent table, it will
through error.
In the above CDS view, I’m joining two tables ZVBAK1(Client independent custom table),
VBAP (Standard Client Dependent table) and I’m using the value as #INHERITED . That meaning
is, if we take any client dependent table in CDS view for joining, automatically the view will
inherit that client dependent to the view.

This is the view in SE11. Automatically MANDT will consider because VBAP table is client
dependent.
ODATA : @OData.publish: true

By using ‘@OData.publish: true’ annotation, we can expose CDS view to External system like
FIORI, UI5 etc.
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX22'
@OData.publish: true
define view ZCDS_DDL_EX22 as select from
vbak as k association[0..*] to vbap as p
on $projection.Sales_order = p.vbeln
{
key k.vbeln as Sales_order,
key p.posnr,
p.matnr,
k.kunnr
}

In the above CDS view, in ‘ON’ condition, used $PROJECTION. If we use it, we need to add
the alias name instead of field name. It will be helpful in a few cases to understand the logic.
Used ‘@OData.publish: true’ annotation also. It means, we are sending the result of CDS view to
external system. But before that one, we need to activate the service (service means connection
between CDS to view to external system).

सतीष कुमार रे ड्डि एम एन Page: 75


We can see one warning symbol beside the annotation @OData.publish: true. If we click on that
symbol we can see like this

Service ZCDS_DDL_EX22_CDS is not activated. CDS view name followed by ‘_CDS’ is


nothing but service name (OData connection name).
For activating the service we need to do below steps.
Execute ‘/IWFND/MAINT_SERVICE’ transaction in SAP GUI.

Click on ‘Add Service’ button.

Provide the system alias name, Technical service name. Technical Service Name we need to pass
as CDS view is proposing. Click on enter button.

सतीष कुमार रे ड्डि एम एन Page: 76


Select the Service name, click on Add Selected Services button as shown in the above image.
In the next screen, select the package, click on continue button.

We can see that service was created and metadata was loaded successfully. It means, Service is created
successfully.

Click on back button  click on filter button, provide the external service name as our newly created
service name (ZCDS_DDL_EX22_CDS), click on contnue button.

सतीष कुमार रे ड्डि एम एन Page: 77


We can see ICF node is in green color. It means, service is activate successfully. Click on SAP GATEwau
Client button, click on Execute button (F8) in the next screen.

Stuts code is coming as 200. It means there is no error. This connection will trigger in correct way.

We can see that one XML format also. If we want to display it in JSON format as shown in in the above
image  select $format = json option. Click on enter button, click on execute button.

Now we can see the code in JSON format.

Instead of XML format SAP is preferring JSON format. Because it is light weight content means, JSON
format will contain memory compare to XML format.

Authorization Check: @AccessControl.authorizationCheck: #CHECK

If we want to provide authorization for a particular user or for one condition, we have to create
one role (Access Control DCL). In that role, we have to mention the CDS view which we want to
apply the authorization check.
Creation of Access Control: Right click on Core Data Services in the left panel 

सतीष कुमार रे ड्डि एम एन Page: 78


Provide the Name, description, click on next button. If we have any Package, we can provide that
package other wise click on Next button, select one template, click on Finish Button.
@EndUserText.label: 'Access control for country'
@MappingRole: true
define role ZAC_EX10 {
grant
select
on
ZCDS_DDL_EX11
where
land1 = 'IN'; }

In the above Access Control, I’m provide the CDS view name (ZCDS_DDL_EX11) then
providing condition land1 = ‘IN’, means the CDS view will display only Indian Companies.
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX11'
@AccessControl.authorizationCheck: #CHECK
define view ZCDS_DDL_EX11 as select from t001 {
key bukrs,
butxt,
ort01,
land1 }

In the above CDS view, we are fetching data from T001 table. It will fetch only Indian
companies because of authorization check. We have to apply one annotation

@AccessControl.authorizationCheck: #CHECK

If we don’t mention it, by default it will treat as authorization check = CHECK.


If we use the above CDS view in program (SE38), It will display the output with restriction
values. If we want to bypass the authorization check in a program, we have to write the select
query in this way.
select * from zcds_ddl_ex11 with PRIVILEGED ACCESS into table @data(lt_t001).

By adding ‘With Privileged Access’ in the select query, we can bypass the authorization check
value.
If we don’t want to apply this authorization check even though you have created Access control
for the CDS view, then we have to pass annotation like this.

@AccessControl.authorizationCheck: #NOT_ALLOWED

If we are passing like authorization check = Not Allowed, it will not consider the ‘Role’ even
though we have created Role.

सतीष कुमार रे ड्डि एम एन Page: 79


We have 2 more components in authorization check.

@AccessControl.authorizationCheck: #NOT_REQUIRED

Means, it will work like #CHECK only. The difference is, if we don’t have any role and we are
applying authorization as #CHECK, then it will through warning message. If we apply
authorization as #NOT_REQUIRED, then it will not through any warning message.
@AccessControl.authorizationCheck: #PRIVILEGED_ONLY

Means, if we expose data to another environment like OData, data will not expose there. By
using association in another CDS view or file path we can expose. But directly we can’t send
data to another environment.
If we use the CDS view which authorization check applied in another CDS view, authorization
check will not apply in that CDS view.
@AbapCatalog.sqlViewName: 'ZCDS_SQL_EX12'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Authorization check'
define view ZCDS_DDL_EX12 as select from ZCDS_DDL_EX11 {
key bukrs,
butxt,
ort01,
land1 }

In the above CDS view, we are fetching the data from another CDS view (authorization check
applied). But this CDS view will fetch all records from T001 table and it authorization check will
apply here.
If we want to get to know where used list of a CDS view, we can check in the below steps.
Right click on CDS view  Get where-used list (Ctrl + Shift + G). We can see the list of
programs / views / roles which are used that base CDS view.

CDS Performance annotations

By using the below annotations, we can improve the performance of CDS view.
@ObjectModel.usageType.serviceQuality: #A
@objectmodel.usagetype.sizeCategory: #L
@objectmodel.usagetype.dataClass: #TRANSACTIONAL

@ObjectModel.usageType.serviceQuality: #A/B/C/D/P/X

सतीष कुमार रे ड्डि एम एन Page: 80


It means, we are giving execution priority to run the view. It means, If we are triggering 2 CDS
views at a time from FIORI or any other application, we need to tell the system that which CDS
view will trigger first by giving options like A,B,C,D,P,X. ‘A’ is the highest priority
@objectmodel.usagetype.sizeCategory: #S/M/L/XL/XXL
By using the above annotation we are telling to the system how much data will trigger by
executing the CDS view. It will work like size category in DDIC table.
@objectmodel.usagetype.dataClass: #TRANSACTIONAL / #MASTER /
#ORGANIZATIONAL / #CUSTOMIZING / #META / #MIXED
By using the above annotation, we are telling to the system that what type data will trigger by
executing the CDS view.
Transactional: Frequenly change data
Master: Rarely change data
Organizational: Very rarely change data
Meta: Unit of measurement / Quantity data
Customizing: Company code / customer code information
Mixed: any combination of the above types

Note: DDHEADANNO is the table to store all annotations used in a CDS view.
Semantics Annotations

@Semantics.amount.currencyCode: 'waerk'

@Semantics.quantity.unitOfMeasure: 'vrkme'

If we are working on amount and quantity fields in CDS, we need to link the currency type and
unit of measurement type fields as show in the below CDS view. These annotations are
mandatory in CDS View Entity.
@AbapCatalog.sqlViewName: 'ZSQL_FOLK24'
define view zcds_folk24 as select from vbap {
vbeln,
posnr,
matnr,
waerk,
@Semantics.amount.currencyCode: 'waerk'
netwr,
vrkme,
@Semantics.quantity.unitOfMeasure: 'vrkme'
kwmeng
}

सतीष कुमार रे ड्डि एम एन Page: 81


CDS Entity:
 CDS Entity is available from ABAP 7.55 version on wards
 DDIC SQL View will not create
 Improved performance during CDS view activation (not required create SQL and DDL
Source… Time saving)
 Buffering annotations not supporting
 Client handling is automated, so not required to add those annotations
 @ABAPCatalog.preserveKey: True is absolute. Not required to mention it again
 We can’t apply select * in CDS entity

@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'test'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity zcds_folk23 as select from vbak {
vbeln,
audat,
kunnr
}

सतीष कुमार रे ड्डि एम एन Page: 82


VDM (Virtual Data Model)
VDM is a proxy for CDS View. With VDM we can expose data to embedded S/4 HANA system
or BI/BW system.
VDM types. 1. Private View 2. Interface (it is again two types, i. Basic View ii. Composite
View), 3. Consumption View.
 The standard Private view name will start with ‘_P’. It means, it is private view and
better to don’t use in any another view.
 @vdm.private: true This annotation will use to set the view as Private.
 @vdm.viewType: #BASIC / #COMPOSITE / #CONSUMPTION This is the annotation to provide
type of that view.

@VDM.viewType: #CONSUMPTION
@Analytics.query: true

@VDM.viewType: #COMPOSITE
@Analytics.dataCategory: #CUBE

@VDM.viewType: #BASIC @VDM.viewType: #BASIC


@Analytics.dataCategory: #DIMENSION @Analytics.dataCategory: #FACT

SAP is recommended to create Basic views on top of tables. We can create on top of another
CDS view also, but SAP will not recommend it. Composite view should create on top of Basic
view. On top of database table also we can create Composite view, but SAP will not recommend
it. Consumption view should create on top of Composite view. We can create Consumption view
on top of database table and Basic view also, but it is not recommended.
Data Category types:
#Dimension: This annotation is telling to the system that, you need to allow master data.
#Fact: This annotation telling to the system that, you need to allow transaction data.
#Cube: This annotation is telling to the system that, you need to allow transaction data and
master data.
For Basic view and composite view we need to mention that @Analytics.dataCategory:
#DIMENSION / #FACT .

For Consumption view, we need not to write @Analytics.dataCategory annotation. We need


to pass @Analytics.query: true .

सतीष कुमार रे ड्डि एम एन Page: 83


@AbapCatalog.sqlViewName: 'ZSQL_FOLK25'
@EndUserText.label: 'testing'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #DIMENSION
define view zcds_folk25 as select from kna1 {
key kunnr,
name1,
ort01,
land1
}

@AbapCatalog.sqlViewName: 'ZSQL_FOLK26'
@EndUserText.label: 'testing'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #DIMENSION
define view zcds_folk26 as select from mara association[1..*] to makt on
mara.MATNR = MAKT.matnr {
key matnr,
mtart,
matkl,
makt.maktx
}

@AbapCatalog.sqlViewName: 'ZSQL_FOLK27'
@EndUserText.label: 'testing'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #FACT
define view zcds_folk27 as select from vbak association to vbap on vbak.vbeln
= VBAP.vbeln {
key vbeln,
key vbap.posnr,
audat,
kunnr,
vbap.matnr,
vbap.kwmeng,
vbap.netwr
}

@AbapCatalog.sqlViewName: 'ZSQL_FOLK28'
@EndUserText.label: 'TESTING'
@VDM.viewType: #COMPOSITE
@Analytics.dataCategory: #CUBE
define view ZCDS_FOLK28 as select from zcds_folk27 as SO association to
zcds_folk25 as CUST on SO.kunnr = CUST.kunnr
association to
zcds_folk26 as MAT on SO.matnr = MAT.matnr {
key SO.vbeln,
key SO.posnr,
SO.audat,
SO.kunnr,
SO.matnr,
SO.kwmeng,

सतीष कुमार रे ड्डि एम एन Page: 84


SO.netwr,
CUST.name1,
CUST.ort01,
CUST.land1,
MAT.maktx
}

@AbapCatalog.sqlViewName: 'ZSQL_FOLK29'
@EndUserText.label: 'TESTING'
@VDM.viewType: #CONSUMPTION
@Analytics.query: true
define view ZCDS_FOLK29 as select from ZCDS_FOLK28 {
key vbeln,
key posnr,
audat,
kunnr,
matnr,
@DefaultAggregation: #SUM
@AnalyticsDetails.query.axis: #COLUMNS
kwmeng,
@DefaultAggregation: #SUM
@AnalyticsDetails.query.axis: #COLUMNS
netwr,
name1,
@AnalyticsDetails.query.axis: #ROWS
ort01,
@AnalyticsDetails.query.axis: #ROWS
land1,
maktx
}

If we want add rows or columns automatically in RSRT transaction, we need to add the
annotations: @AnalyticsDetails.query.axis: #ROWS / #COLUMNS

We can expose the data to analytics RSRT t.code.


Execute RSRT T.Code.

Pass the SQL view name from CDS view. Add ‘2C’ as the prefix to the SQL view name, click
on execute button.

सतीष कुमार रे ड्डि एम एन Page: 85


It will display the output like this. If you want to add any rows, we can add here.

RSRTS_ODP_DIS is the transaction code to view analyze Transient Provider.

सतीष कुमार रे ड्डि एम एन Page: 86


CDS Table Function
If we are not able to write something in CDS view then we can use table function. Table function
is one place where we can write SQL code. For using Table function, we need to follow the
below steps.
 Create table function
 Create one AMDP class & methods
 Use that table function in multiple CDS views.

Table Function Creation:


Right click on package in ABAP perspective  New  Expand Core Data Services  select
Data Definition  Click on Next button  Select TR  select template as ‘Define Table
Function with Parameters’  click on Finish Button.
@EndUserText.label: 'table function demo'
define table function zcds_table_func1
//with parameters parameter_name : parameter_type
returns {
client : abap.clnt;
Product_order : aufnr ;
Order_type : auart ;
routing : co_aufpl ;
counter : co_aplzl;
std_val1 : vgwrt ;
std_val2 : vgwrt ;

}
implemented by method zcl_tab_fun=>get_data;

In table function we must use return parameters (CDS view consumable fields) and mention
Class name and method name which will fill the return parameters.
There is no mandatory semantics for table function and don’t provide SQL name also.

सतीष कुमार रे ड्डि एम एन Page: 87


AMDP Class for table function
CLASS zcl_tab_fun DEFINITION PUBLIC .
PUBLIC SECTION.
interfaces if_amdp_marker_hdb.
class-methods: get_data for table function zcds_table_func1.
ENDCLASS.

CLASS zcl_tab_fun IMPLEMENTATION.


method get_data BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY USING aufk afko afvv afvc.
lt_aufk = select mandt, aufnr, auart from aufk;
lt_afko = select aufnr, aufpl from afko where aufnr in ( select aufnr from :lt_aufk
);
lt_hours = select afvv.aufpl, afvv.aplzl, afvv.vgw01, afvv.vgw02, afvv.iedd,
afvc.vornr from afvv as afvv inner join afvc as afvc on afvv.aufpl = afvc.aufpl and
afvv.aplzl = afvc.aplzl;
return select hdr.mandt as client, hdr.aufnr as product_order,
hdr.auart as order_type, oper.aufpl as routing,
hrs.aplzl as counter, hrs.vgw01 as std_val1, hrs.VGW02 as std_val2
from :lt_aufk as hdr inner join :lt_afko as oper
on hdr.aufnr = oper.aufnr
left outer join :lt_hours as hrs on oper.aufpl = hrs.aufpl;

ENDMETHOD.
ENDCLASS.

In class declaration interface IF_AMDP_MARKER_HDB should be consider and provide


method as static method. For that method we need to write extra code as
FOR TABLE FUNCTION <Table Function Name>. It is mandatory otherwise will through
error. In method implementation, need to provide like this
BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT USING <table1 table2>.
Required to write like RETURN select statement to fill return parameters (Table function return
parameters).

One more real time example for table function:


@EndUserText.label: 'testing'
define table function zaoh2_cds24
returns {
client : abap.clnt;
vbeln : vbeln_va;
POSNR : posnr_va;
AUDAT : audat;
MATNR : matnr;
@Semantics.quantity.unitOfMeasure: 'VRKME'
--@SEMANTICS.amount.currencyCode: ''
KWMENG : kwmeng; --100, 259
VRKME : vrkme;
DEL_NUM1 : vbeln_vl;

सतीष कुमार रे ड्डि एम एन Page: 88


DEL_ITEM1 : posnr_vl;
DEL_DATE1 : audat;
@Semantics.quantity.unitOfMeasure: 'VRKME'
DEL_QTY1 : kwmeng;
DEL_NUM2 : vbeln_va;
DEL_ITEM2 : posnr_va;
DEL_DATE2 : audat;
@Semantics.quantity.unitOfMeasure: 'VRKME'
DEL_QTY2 : kwmeng;
DEL_NUM3 : vbeln_va;
DEL_ITEM3 : posnr_va;
DEL_DATE3 : audat;
@Semantics.quantity.unitOfMeasure: 'VRKME'
DEL_QTY3 : kwmeng;
@Semantics.quantity.unitOfMeasure: 'VRKME'
TOT_DEL_QTY : kwmeng;
@Semantics.quantity.unitOfMeasure: 'VRKME'
PEND_QTY : kwmeng;

}
implemented by method zcl_aoh2_amdp7=>final_output;

We need to mailtain @Semantics.quantity.unitOfMeasure: 'VRKME'


If we don’t use the above semantics and used this table function in any other CDS view, it will
through error. So we need to maintain this semantics.
CLASS zcl_AOH2_AMDP7 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
class-METHODS: final_output FOR TABLE FUNCTION ZAOH2_CDS24. " EXPORTING
VALUE(lt_final) type tt_final.
ENDCLASS.

CLASS ZCL_AOH2_AMDP7 IMPLEMENTATION.


method final_output BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT OPTIONS
READ-ONLY USING VBAK VBAP LIKP LIPS.
declare lv_so_count int = 0; -- SO IT No
of records
declare I int = 0;
declare M int = 0;
DECLARE LV_VBELN "$ABAP.TYPE( VBELN_VA )"; -- DECLAR LV_VBELN NVARCHAR(10)
DECLARE LV_POSNR "$ABAP.TYPE( POSNR_VA )";
DECLARE LV_DEL_COUNT INT = 0; -- Delivery
IT No of records
declare lv_del_qty "$ABAP.TYPE( LFIMG )" = 0; -- Tot Del Qty

DECLARE LT_FINAL TABLE ( CLIENT "$ABAP.TYPE( MANDT )" ,


VBELN "$ABAP.TYPE( VBELN_VA )" ,
POSNR "$ABAP.TYPE( POSNR_VA )" ,
AUDAT "$ABAP.TYPE( AUDAT )" ,

सतीष कुमार रे ड्डि एम एन Page: 89


MATNR "$ABAP.TYPE( MATNR )" ,
KWMENG "$ABAP.TYPE( KWMENG )" ,
VRKME "$ABAP.TYPE( VRKME )",
DEL_NUM1 "$ABAP.TYPE( VBELN_VL )" ,
DEL_ITEM1 "$ABAP.TYPE( POSNR_VL )" ,
DEL_DATE1 "$ABAP.TYPE( AUDAT )" ,
DEL_QTY1 "$ABAP.TYPE( KWMENG )" ,
DEL_NUM2 "$ABAP.TYPE( VBELN_VA )" ,
DEL_ITEM2 "$ABAP.TYPE( POSNR_VA )" ,
DEL_DATE2 "$ABAP.TYPE( AUDAT )" ,
DEL_QTY2 "$ABAP.TYPE( KWMENG )" ,
DEL_NUM3 "$ABAP.TYPE( VBELN_VA )" ,
DEL_ITEM3 "$ABAP.TYPE( POSNR_VA )" ,
DEL_DATE3 "$ABAP.TYPE( AUDAT )" ,
DEL_QTY3 "$ABAP.TYPE( KWMENG )" ,
TOT_DEL_QTY "$ABAP.TYPE( KWMENG )" ,
PEND_QTY "$ABAP.TYPE( VBELN_VA )"

);

LT_SALES = select h.vbeln, i.posnr, h.audat, i.matnr, i.kwmeng, I.VRKME from


vbak as h inner join vbap as i
on h.vbeln = i.vbeln where H.mandt = SEssion_context( 'CLIENT' ) and i.kwmeng
!= 0; --<> NE

LT_DELIVERY = SELECT h.vbeln, i.posnr, h.lfdat, i.lfimg, i.vgbel, i.vgpos


from likp as h inner join lips as i
on h.vbeln = i.vbeln where h.mandt = session_context( 'CLIENT' ) and i.lfimg
!= 0;

lv_so_count = record_count( :lt_sales );

for I in 1..lv_so_count do
LT_FINAL.client[ I ] = SEssion_context( 'CLIENT' );
LT_FINAL.VBELN[ I ] = :lt_sales.vbeln[ I ];
lt_final.posnr[ I ] = :lt_sales.posnr[ I ];
lt_final.audat[ I ] = :lt_sales.audat[ I ];
lt_final.matnr[ I ] = :lt_sales.matnr[ I ];
lt_final.kwmeng[ I ] = :lt_sales.kwmeng[ I ];
lt_final.VRKME[ I ] = :lt_sales.VRKME[ I ];

LV_VBELN = :LT_FINAL.VBELN[ I ];
LV_POSNR = :LT_FINAL.POSNR[ I ];

lt_tem_del = select * from :lt_delivery where vgbel = LV_VBELN AND VGPOS =


LV_POSNR; -- Fetching Delivery Info for perticular SO

if IS_EMPTY ( :lt_tem_del ) then

else
LV_DEL_COUNT = RECORD_COUNT( :LT_TEM_DEL ); -- No of recoreds
in Delivery IT

for M in 1..lv_del_count do
if M = 1 then
lt_final.del_num1[ I ] = :lt_tem_del.vbeln[ M ];
lt_final.del_item1[ I ] = :lt_tem_del.posnr[ M ];

सतीष कुमार रे ड्डि एम एन Page: 90


lt_final.del_date1[ I ] = :lt_tem_del.lfdat[ M ];
lt_final.del_qty1[ I ] = :lt_tem_del.lfimg[ M ];
lv_del_qty = lv_del_qty + :lt_tem_del.lfimg[ M ];

elseif M = 2 then
lt_final.del_num2[ I ] = :lt_tem_del.vbeln[ M ];
lt_final.del_item2[ I ] = :lt_tem_del.posnr[ M ];
lt_final.del_date2[ I ] = :lt_tem_del.lfdat[ M ];
lt_final.del_qty2[ I ] = :lt_tem_del.lfimg[ M ];
lv_del_qty = lv_del_qty + :lt_tem_del.lfimg[ M ];

elseif M = 3 then
lt_final.del_num3[ I ] = :lt_tem_del.vbeln[ M ];
lt_final.del_item3[ I ] = :lt_tem_del.posnr[ M ];
lt_final.del_date3[ I ] = :lt_tem_del.lfdat[ M ];
lt_final.del_qty3[ I ] = :lt_tem_del.lfimg[ M ];
lv_del_qty = lv_del_qty + :lt_tem_del.lfimg[ M ];
end if;

end for;
lt_final.tot_del_qty[ I ] = lv_del_qty;
lt_final.pend_qty[ I ] = :lt_sales.kwmeng[ I ] - :lt_final.tot_del_qty[ I ]
;

lv_del_qty = 0;
lt_tem_del = select * from :lt_tem_del where 1 = 2;
end if;

END FOR ;

RETURN :LT_FINAL;

ENDMETHOD.
ENDCLASS.

Once the method is completed, we can use this Table Function in any number of CDS views.
@AbapCatalog.sqlViewName: 'ZAOH2_SQL25'
@EndUserText.label: 'TESTING'
define view zaoh2_cds25 as select from zaoh2_cds24{
*
}

सतीष कुमार रे ड्डि एम एन Page: 91


HANA Search
3 types of HANA searches are there.
1. Fuzzy Search
2. Exact Search
3. Linguistic Search
First we will check in ABAP Layer.
I’ve created one table.

Here I’m using ‘KUNNR’ as data element. Let me create entries for it.

I’ve given something customer name (not full name). It is displaying something in one popup
related to the input field. How it is coming. For that data element, one search help is created. Let
me check that one.

सतीष कुमार रे ड्डि एम एन Page: 92


I’ve opened the data element. In ‘Further Characteristics’ tab, we can see the search help name.
If we open it search help..

One collective search created. Click on ‘Included search helps’ tab. We can see one more search
help. Double click on that search help. It will contain one more search help.

We can see that Autosuggest in input fields check box and Multi-column full text search
(database-specific) check box selected. And Accuracy value for error-tolerant full test search is

सतीष कुमार रे ड्डि एम एन Page: 93


maintained as ‘0,8’. It means, 0.8 nothing but 80%. If our text match around 80%, then related
values will show in the popup.
Let me use the different data element in the table level.

I’ve maintained the above search help.

In the search help, I’m not selecting checkboxes so that percentage is also in disable mode now.
Let me try to enter data in table level.

I’m trying to enter ‘CIP’ in customer number, it is not showing anything even though I’ve
created search help.

सतीष कुमार रे ड्डि एम एन Page: 94


Now let me select the ‘Autosuggest in input fields’ check box and ‘Multi-column full text search
check box. Provide some percentage (I’m giving 80%).

Now I’ll try to enter something data in table level.

Here, I’m giving ‘CIP’ in customer number, it is showing related values in popup.
This is called here FUZZY SEARCH, means if we provide something input, system will check
for related values and it will show for select.

Let me provide ‘Accuracy Value for Error-Tolerant Full Text Search’ as ‘1,0’ means ‘1.0’
nothing but 100%.

सतीष कुमार रे ड्डि एम एन Page: 95


Now let me try to enter records in table.

I’m just giving as ‘CIP’ in the customer number. System is not showing related values here. Let
me give some more characters here.

I’ve given ‘CIPLA’ then system is showing one related value, means if we give correct word
then only it will show something output.
Search help & fuzzy or exact search is not coming for NAME1 and ORT01. If we want to apply
search help, need to create search help for it and need to create index for that field to apply fuzzy
or exact search.

सतीष कुमार रे ड्डि एम एन Page: 96


Now assign this search help for the data element.
How to create index for the field.
Execute ‘ST04’ transaction  Expand Diagnostics folder in left panel  double click on SQL
Editor.
Write the syntax like this
Create FULLTEXT index<Index name> ON <Table name>(“Field Name”) FAST
PREPROCESSOR OFF
Here ‘FAST PREPROCESSOR’ should be on by default we don’t maintain it in syntax (it’s
optional).
FAST PREPROCESSOR means
1. Normalization
2. Tokenization
Normalization means, if we give something word like ‘bring’, system will search for ‘bring’,
‘Bring’, ‘BRING’…

सतीष कुमार रे ड्डि एम एन Page: 97


Tokenization search means, If we give something word like ‘bring’, system check is there any
statement which will contain the above word…
In SQL Editor I’m writing the syntax as below.
create fulltext index AB on ZCUST_INFO1("NAME1")

Click on execute button. It will show one success message. We need to check index is created or
not for that field in table level.
Open the table  click on ‘Utilities’ menu button  Database Object  Display

Now try to enter something value in that field,

Search help is coming for NAME1 field. We have to do the above steps for ORT01 also.
Coming to Linguistic search, if we give something word like ‘DO’, then system will check for
‘DO’, ‘DID’, ‘DONE’, ‘DOING’, ‘DONOT’, ‘DID NOT’. It may search for a few more words
which meaning nearly equal to ‘DO’. This is called Linguistic Search. But in ABAP layer it is
not possible. In HANA DB we can do it.
We have one more search in in Hana database that is ‘FULL TEXT’ SEARCH.
We can see the index name and field added to the index.

Let me check the searches in Hana DB..

सतीष कुमार रे ड्डि एम एन Page: 98


Execute ‘ST04’ transaction  Expand Diagnostics folder in left panel  double click on SQL
Editor.
Write the syntax like this
select * from zcust_info1 where contains("NAME1", 'SATHI', FUZZY)

Here, I’m fetching all records ZCUST_INFO1-NAME1 which will contain the letters as
‘SATHI’.

It is displaying like this.


select * from zcust_info1 where contains("NAME1", 'SATHI', FUZZY)

In this statement, I’ve used ‘FUZZY’. If we want to apply EXACT & LINGUISTIC we can
apply that one also here.

सतीष कुमार रे ड्डि एम एन Page: 99


ABAP 7.4 Features
1. Pass Value to variable
Before 7.4
data lv_text type char30.
lv_text = 'Shree Janani Foundation'.

From 7.4
data(lv_matnr) = '123'.
In the above line lv_matnr = 123 will come the data type and length should be char3.
Because we are providing 3 characters. But I want to consider as char40(data element of
MATNR is char40) even though I pass 3 characters.
data(lv_matnr1) = new matnr( '123' ).
Here just I’m using reference of matnr. It will consider the data type and length from
MATNR data element.
data(lv_netwr) = new netwr('123.11').
Here also lv_netwr data type length should consider from NETWR data element.

2. Work area in select query


Before 7.4
data wa type mara.
select * from groupmara into wa_mara where matnr = '0001'.

From 7.4
SELECT SINGLE * FROM mara
INTO @DATA(wa_mara) WHERE matnr = '0001'.

3. Internal table in select query


Before 7.4
types: BEGIN OF TY_MARA,
MATNR TYPE MATNR,
MTART TYPE MTART,
MEINS TYPE MEINS,
END OF TY_MARA.
DATA: IT_MARA TYPE TABLE OF TY_MARA,
WA_MARA TYPE TY_MARA.
SELECT MATNR MTART MEINS FROM MARA
INTO TABLE IT_MARA WHERE MTART = 'FERT'.
LOOP AT IT_MARA INTO WA_MARA.
ENDLOOP.

From 7.4
SELECT matnr, mtart, meins
FROM mara
INTO TABLE @DATA(it_mara)
WHERE mtart = 'FERT'.

From 7.5
SELECT FROM mara
FIELDS matnr, mtart, meins

सतीष कुमार रे ड्डि एम एन Page: 100


WHERE mtart = 'FERT'
INTO TABLE @DATA(it_mara) .

Here I’ve taken FIELDS <f1>, <f2> . By writing like this we have one advantage. By clicking CTRL
+ Space, it will display the fields from that table. This feature is not available before 7.5 version.
After into table <IT Name>, system will not accept where condition. If you want to give where
condition, you can give before into table <IT Name>.

4. Joins
Before 7.4
TYPES: BEGIN OF ty_materials,
matnr TYPE matnr,
mtart TYPE mtart,
maktx TYPE maktx,
spras TYPE spras,
END OF ty_materials.
DATA: it_materials TYPE TABLE OF ty_materials,
wa_materials TYPE ty_materials.
SELECT mara~matnr mara~mtart makt~maktx makt~spras
INTO TABLE it_materials
FROM mara INNER JOIN makt ON mara~matnr = makt~matnr
WHERE mara~mtart = 'FERT'
AND makt~spras = ' '.

From 7.4
SELECT mara~matnr, mara~mtart, makt~maktx, makt~spras
FROM mara INNER JOIN makt ON mara~matnr = makt~matnr
WHERE mara~mtart = @lv_mtart
AND makt~spras = @lv_spras
INTO TABLE @DATA(it_materials).

Right outer join is not possible before ABAP 7.4. From ABAP 7.4 onwards it will work. In place of
Join, keep Right Outer Join or Left Outer Join. It will work accordingly.
5. Using for all entries
Before 7.4
TYPES: BEGIN OF ty_mara,
matnr TYPE matnr,
mtart TYPE mtart,
END OF ty_mara,
BEGIN OF ty_makt,
matnr TYPE matnr,
maktx TYPE maktx,
END OF ty_makt.
DATA: it_mara TYPE TABLE OF ty_mara,
it_makt TYPE TABLE OF ty_makt.
SELECT matnr mtart FROM mara INTO TABLE it_mara
WHERE mtart = 'FERT'.
IF it_mara IS NOT INITIAL.
SELECT matnr maktx FROM makt INTO TABLE it_makt
FOR ALL ENTRIES IN it_mara
WHERE matnr = it_mara-matnr.
ENDIF.

सतीष कुमार रे ड्डि एम एन Page: 101


From 7.4
SELECT matnr, mtart
FROM mara
INTO TABLE @DATA(it_mara)
WHERE mtart = 'FERT'.
IF it_mara IS NOT INITIAL.
SELECT *
FROM makt
INTO TABLE @DATA(it_makt)
FOR ALL ENTRIES IN @it_mara
WHERE matnr = @it_mara-matnr.
ENDIF.

6. Using CASE in select query


Before 7.4
There is no concept of Case expression in select query before7.4 version.

From 7.4
DATA: lv_fert TYPE text30 VALUE 'Finished Products',
lv_halb TYPE text30 VALUE 'Semifinished Products',
lv_other TYPE text30 VALUE 'Other Material Type'.

SELECT SINGLE matnr, mtart,


CASE
WHEN mtart = 'FERT' THEN @lv_fert
WHEN mtart = 'HALB' THEN @lv_halb
ELSE @lv_other
END AS material_type
FROM mara
INTO @DATA(wa_mara)
WHERE matnr = '000001-002'.

WRITE:/ 'Material Type :', wa_mara-material_type.

7. Initialize values in work area


Before 7.4
Wa_mara-matnr = '0001'.
Wa_mara-mtart = 'FERT'.

From 7.4
TYPES: BEGIN OF ty_mara,
matnr TYPE mara-matnr,
mtart TYPE mara-mtart,
END OF ty_mara.

DATA: wa_mara TYPE ty_mara.


wa_mara = VALUE #( matnr = 0001 mtart = 'FERT' ).

सतीष कुमार रे ड्डि एम एन Page: 102


8. Initialize Internal table values
Before 7.4
Need to fill work area, then pass the values to Internal table by using append / insert / collect
statements.

From 7.4
TYPES: BEGIN OF ty_mara,
matnr TYPE mara-matnr,
mtart TYPE mara-mtart,
END OF ty_mara.
DATA: it_mara TYPE TABLE OF ty_mara.

it_mara = VALUE #( ( matnr = 0001 mtart = 'FERT' )


( matnr = 0001 mtart = 'HALB' )
( matnr = 0003 mtart = 'HAWA' )
( matnr = 0004 mtart = 'FERT' )
( matnr = 0005 mtart = 'FERT' )
( matnr = 0006 mtart = 'HALB' )
( matnr = 0007 mtart = 'HAWA' ) ).

In the above syntax we have written like VALUE #(. We are declaring the internal table and using
here. If write VALUE #(, it will consider the IT_MARA structure.

For example, if we are not declaring the internal table, just filling the values like table type we
can write like this.
TYPES: BEGIN OF ty_mara,
matnr TYPE mara-matnr,
mtart TYPE mara-mtart,
END OF ty_mara.
types: tt_mara TYPE TABLE OF ty_mara WITH EMPTY KEY.
data(lt_mara) = VALUE tt_mara( ( matnr = 0001 mtart = 'FERT' )
( matnr = 0001 mtart = 'HALB' )
( matnr = 0003 mtart = 'HAWA' )
).
I’ve mentioned like VALUE TT_MARA, means we are using the structure TT_MARA.
types: tt_mara TYPE TABLE OF ty_mara WITH EMPTY KEY.
Here, we need to mention WITH EMPTY KEY at the end of that statement. Otherwise, it will
show error.

If we want to fill internal table by using different internal tables, we can follow the below syntax.
it_final = value #( for wa_mara in lt_mara where ( mtart = 'HAWA' )
FOR WA_MARD IN LT_MARD WHERE ( MATNR = WA_MARA-
MATNR )
FOR WA_MARC IN LT_MARC WHERE ( MATNR = WA_MARA-
MATNR )
( MATNR = WA_MARA-MATNR
MATKL = WA_MARA-MATKL
WERKS = WA_MARD-WERKS
LGORT = WA_MARD-LGORT
PSTAT = WA_MARC-PSTAT ) ).

सतीष कुमार रे ड्डि एम एन Page: 103


If we have multiple values in LT_MARC, LT_MARD system will loop those internal tables
internally.

If we want to get to know the index number in for loop, we can write like this.

lt_mara = value #( base lt_mara for ls_material in lt_material index


into lv_index where ( mtart = 'ROH' )
( matnr = ls_material-matnr mtart = ls_material-mtart
matkl = ls_material-matkl ) ).

Just assume we are filling internal table with 3 records. If try to insert into that same internal
table with a few more data, then the previous data will erase and new data will insert. To
overcome it, we can follow the below steps.
TYPES: BEGIN OF ty_mara,
matnr TYPE mara-matnr,
mtart TYPE mara-mtart,
END OF ty_mara.
types: tt_mara TYPE TABLE OF ty_mara WITH EMPTY KEY.
data(lt_mara) = VALUE tt_mara( ( matnr = 0001 mtart = 'FERT' )
( matnr = 0001 mtart = 'HALB' )
( matnr = 0003 mtart = 'HAWA' )
).

lt_mara = VALUE tt_mara( BASE LT_MARA


( matnr = 0001 mtart = 'FERT' )
( matnr = 0001 mtart = 'HALB' )
( matnr = 0003 mtart = 'HAWA' )
( matnr = 0003 mtart = 'FERT' )
).
By using BASE <Internal table>, we keep the existing data in the internal table.

9. Move corresponding fields from one internal table to another internal table
Before 7.4
move-CORRESPONDING lt_kna1 to it_kna1.
From 7.4
Here, if the name is same in both internal tables, those data only will move.

From 7.4
types: BEGIN OF ty_kna1,
kunnr type kunnr,
xyz type char35,
end of ty_kna1.
data it_kna1 type TABLE of ty_kna1.

select kunnr, name1, ort01 from kna1 into TABLE @data(lt_kna1).


* Method1
* it_kna1 = CORRESPONDING #( lt_kna1 mapping kunnr = kunnr
* xyz = name1 ).
* Method2
it_kna1 = VALUE #( for wa_kna1 in lt_kna1 ( kunnr = wa_kna1-kunnr
xyz = wa_kna1-name1 ) ).

सतीष कुमार रे ड्डि एम एन Page: 104


10. Two internal tables data merge into one internal table
Before 7.4
LOOP AT lt_vbak INTO ls_vbak.
ls_final-vbeln = ls_vbak-vbeln.
ls_final-audat = ls_vbak-audat.
ls_final-kunnr = ls_vbak-kunnr.
READ TABLE lt_kna1 INTO ls_kna1 WITH KEY kunnr = ls_vbak-kunnr.
IF sy-subrc = 0.
ls_final-name1 = ls_kna1-name1.
ENDIF.
APPEND ls_final TO lt_final.
CLEAR: ls_final, ls_vbak, ls_kna1.
ENDLOOP.

From 7.4
it_final = VALUE #( for ls_vbak in lt_vbak ( vbeln = ls_vbak-vbeln
audat = ls_vbak-audat
kunnr = ls_vbak-kunnr
name1 = VALUE #( lt_kna1[
kunnr = ls_vbak-kunnr ]-name1 OPTIONAL ) ) ).

11. Rad table based on index


Before 7.4
read table it_mara into wa_mara INDEX 2.

From 7.4
DATA(wa_mara) = it_mara[ 2 ]. "Read index 2 from IT_MARA
Here SY-SUBRC won’t work. So we have to take as below
TRY .
DATA(wa_mara) = it_mara[ 51 ]. "Read 51 index will fail because onl
y 50 records are there
CATCH cx_sy_itab_line_not_found.
WRITE:/ 'Error Reading Record'.
ENDTRY.
WRITE:/ wa_mara-matnr.

12. Read table based on condition


Before 7.4
read table it_mara into wa_mara with key matnr = '002'.

From 7.4
TRY .
DATA(wa_mara) = it_mara[ matnr = '0001' mtart = 'FERT' ].
CATCH cx_sy_itab_line_not_found.
WRITE:/ 'Error Reading Record'.
ENDTRY.
Here we are using Try, Catch blocks. If we are not getting the data to the work area it will
through error. That is why we have used Try, Catch blocks.
If we don’t want to use this Try and Catch blocks, we can use the below syntax.

सतीष कुमार रे ड्डि एम एन Page: 105


data(wa_mara) = VALUE #( it_mara[ matnr = '0001' mtart = 'FERT' ] OPTIO
NAL ).

By using the above syntax, if data is not available in internal table with given condition, then it
will not go to dump
We can apply the below syntax also.
data(wa_mara2) = value #( it_mara[ 10000 ] DEFAULT abap_false ).
In the above case, if the value is not available then by defalt abap_false value will come to the
work area.

We can go for field-symbols also to fetch data into work area.


assign lt_mara[ matnr = 'TG10' ] to FIELD-SYMBOL(<fs_mara>).
if sy-subrc = 0.

Endif.
If the value is not available, system will show sy-subrc value ‘4’ in the above case.

If we want to read a single record from internal table, we can write like this.
data(lv_matkl) = value #( lt_mara[ matnr = 'T09' ]-matkl optional ).
if lv_matkl is not INITIAL.

Endif.

13. Check records in internal table


Before 7.4
IF it_mara IS NOT INITIAL.
READ TABLE it_mara TRANSPORTING NO FIELDS WITH KEY matnr = '0001' mtart
= 'FERT' .
IF sy-subrc = 0.
ENDIF.
ENDIF.

From 7.4
IF line_exists( it_mara[ matnr = '0001' mtart = 'FERT' ] ).
WRITE:/ 'Records Exists'.
ENDIF.

14. Get index number from Internal table


Before 7.4
read table it_vbap into wa_vbap with key vbeln = '4'.
if sy-subrc = 0.
lv_ind = sy-index.
endif.

From 7.4
data(lv_ind) = line_index( it_vbap[ vbeln = '4' ] ).

15. Existence check


Before 7.4
parameters p_vbeln type vbeln.
SELECT SINGLE * FROM vbak INTO @DATA(ls_vbak) WHERE vbeln = @p_vbeln.

सतीष कुमार रे ड्डि एम एन Page: 106


IF ls_vbak is not INITIAL.
ELSE.
ENDIF.

From 7.4
parameters p_vbeln type vbeln.
SELECT SINGLE @abap_true FROM vbak INTO @DATA(lv_check) WHERE vbeln = @
p_vbeln.
IF lv_check = abap_true.
ELSE.
ENDIF.
16. Sub query
Before 7.4
Before ABAP 7.4, there is no concept of sub query.

From 7.4
parameters p_kunnr type kunnr.
select vbeln, aedat, kunnr from vbak into TABLE @data(lt_vbak)
where kunnr = ( select kunnr from kna1 where kunnr = @p_kunnr ).

17. Field symbols in loop statement


Before 7.4
TYPES: BEGIN OF ty_vbak,
vbeln TYPE vbeln,
vbtyp TYPE vbtyp,
kunnr TYPE kunnr,
doc_type(40) TYPE c,
END OF ty_vbak.

DATA: it_vbak TYPE TABLE OF ty_vbak,


wa_vbak TYPE ty_vbak.
FIELD-SYMBOLS <fs_vbak> TYPE ty_vbak.
SELECT vbeln vbtyp kunnr FROM vbak INTO TABLE it_vbak.

LOOP AT it_vbak INTO <fs_vbak>.


IF <fs_vbak>-vbtyp = 'C'.
<fs_vbak>-doc_type = 'SO'.
ELSEIF <fs_vbak>-vbtyp = 'A'.
<fs_vbak>-doc_type = 'Inquery'.
ENDIF.
ENDLOOP.

From 7.4
SELECT vbeln, vbtyp, kunnr
* CASE vbtyp
* WHEN 'A'
* THEN 'SO'
* WHEN 'C'
* THEN 'Inquery'
* END AS doc_type
FROM vbak INTO TABLE @DATA(it_vbak).

सतीष कुमार रे ड्डि एम एन Page: 107


LOOP AT it_vbak ASSIGNING FIELD-SYMBOL(<fs_vbak>).
IF <fs_vbak>-vbtyp = 'C'.
<fs_vbak>-doc_type = 'SO'.
ELSEIF <fs_vbak>-vbtyp = 'A'.
<fs_vbak>-doc_type = 'Inquery'.
ENDIF.
ENDLOOP.

18. Aggregate Functions (Sum, Count, Avg)


Before 7.4
Aggregate functions are not possible before AS ABAP 7.4

From 7.4
select mara~matnr,
mard~lgort,
count( mard~matnr ) as count_mat,
count( mard~werks ) as count_plant,
sum( mard~labst ) as unrest,
sum( mard~insme ) as qua_insp_stock
from mara inner join mard
on mara~matnr = mard~matnr
GROUP BY mara~matnr, mard~lgort
into TABLE @data(it_mat).
Note:
Aggregate functions are not possible with for all entries concept.
We can apply aggregate functions for one internal table with out for all entries. By using that
internal table, we can write select query and for all entries with another table.

select matnr, lgort, count_mat from @it_mat as mat_data into TABLE @data
(lt_material).

Here I’ve mentioned alias name as mat_data. It’s mandatory here. If we don’t maintain, it
will through error.

If we are working on aggregate functions, where condition will not work. Instead of that one,
we need to pass having condition.
DATA lv_kunnr TYPE kunnr.
SELECT-OPTIONS s_kunnr FOR lv_kunnr.
SELECT kunnr, SUM( netwr ) AS net_value FROM vbak
INTO TABLE @DATA(lt_vbak)
GROUP BY kunnr HAVING kunnr IN @s_kunnr.

19. Arithmetic Functions (Round, Ceil, Flour)


Before 7.4
There is not Arithmetic function before AS ABAP 7.4

सतीष कुमार रे ड्डि एम एन Page: 108


From 7.4
select netwr,
ceil( netwr ) as ceil_netwr,
floor( netwr ) as floor_netwr,
round( netwr, 1 ) as round_netwr
from vbak
where vbeln = '0000000043'
into table @data(lt_vbap).

cl_demo_output=>display(
EXPORTING
data = lt_vbap " Text or Data
).

20. Concatenate in select query


Before 7.4
Concatenate option is not possible before AS ABAP 7.4

From 7.4
data lv_kunnr type kunnr.
select-OPTIONS s_kunnr for lv_kunnr.
select kunnr,
name1,
kunnr && ':' && name1 as customer
from kna1 where kunnr in @s_kunnr into table @data(lt_kna1).
21. Concatenate variables
Before 7.4
data lv_str type char100.
concatenate lv_text lv_text1 into lv_str.

From 7.4
data(lv_text) = 'Shree Janani Foundation'.
data(lv_text1) = 'SJF'.
data(lv_op) = lv_text && lv_text1 .
data(lv_op1) = |{ 'Shree Janani' } { 'Foundation' }|.
data(lv_op2) = |{ 'Shree Janani' } { ' ' }| && lv_text1.
22. Union all in select query
Before 7.5
Before AS ABAP 7.4, there is no Union all concept. Instead of it we were using append
statement for inserting data in the same (2nd IT) internal table.

From 7.5
TABLES VBAK.
SELECT-OPTIONS S_VBELN FOR VBAK-VBELN.
SELECT FROM VBAP
FIELDS VBELN,
POSNR,
MATNR,
matkl

सतीष कुमार रे ड्डि एम एन Page: 109


WHERE VBELN IN @S_VBELN
and matkl = 'L001'
union
SELECT FROM VBAP
FIELDS VBELN,
POSNR,
MATNR,
matkl
WHERE VBELN IN @S_VBELN
and matkl = 'ZMTN'
INTO TABLE @DATA(LT_VBAP).

23. Object declaration for a class


Before 7.4
CLASS zcl_material DEFINITION.
ENDCLASS.
CLASS zcl_material IMPLEMENTATION.
ENDCLASS.
DATA obj_mat TYPE REF TO zcl_material.
CREATE OBJECT obj_mat.

From 7.4
data(obj_mat1) = new zcl_material( ).
24. Internal declaration for importing data from a method
Before 7.4
data it_mara type table of mara.
obj_mat->get_mat(
EXPORTING
iv_matnr = p_matnr
IMPORTING
lt_mara = it_mara
).

From 7.4
obj_mat->get_mat(
EXPORTING
iv_matnr = p_matnr
IMPORTING
lt_mara = data(it_mara)
).
25. Type compatibility convert
Before 7.4
There is no option to convert type compatibility variable before AS ABAP 7.4

From 7.4
parameter p_matnr type char5.
data it_mara type table of mara.
obj_mat->get_mat(
EXPORTING
iv_matnr = conv #( p_matnr )

सतीष कुमार रे ड्डि एम एन Page: 110


IMPORTING
lt_mara = it_mara
).
Here p_matnr data type character and length is 5. But in the method for iv_matnr, we should
pass the input value as character 10. For this reason, need to convert p_matnr to character 10
dynamically. By using above syntax we can convert it.

26. Cross Join


Before 7.4
Before ABAP 7.4 there is not concept of Cross Join. But instead of cross join we can use
inner join.
SELECT mandt, sprsl, arbgb, msgnr, text
FROM t000 AS t1 inner JOIN t100 AS
t2 on 1 = 1
INTO TABLE @DATA(lt_final) UP TO 50 ROWS.

Here I’ve mentioned inner join but the functionality will work as cross join only. Because
I’ve mentioned ‘On’ condition as 1 = 1. This condition always true. So it pick the values
from both tables.

From 7.4
Cross join will pick all records from left hand side table and right hand side table.

Table1 Table2
F1 F2 F3 F4
1 000 EN Material
2 100 DE owievli

Output
F1 F2 F3 F4
1 000 EN Material
1 000 DE Owievli
2 100 EN Material
2 100 DE owievli
Requirement:
For each client display the list of possible messages.

SELECT mandt, sprsl, arbgb, msgnr, text


FROM t000 AS t1 CROSS JOIN t100 AS t2
INTO TABLE @DATA(lt_final) UP TO 50 ROWS.

Here ‘ON’ condition is not required

सतीष कुमार रे ड्डि एम एन Page: 111


27. SQL String functions
Before 7.4
Before ABAP 7.4 there is not concept of SQL String functions

From 7.51
DATA: BEGIN OF wa_final,
kunnr TYPE kunnr,
name1 TYPE name1,
END OF wa_final.
DATA it_final LIKE TABLE OF wa_final.
it_final = VALUE #( ( kunnr = ' 123' name1 = ' Shree Janani Foundation'
) ).
SELECT
concat( kunnr, name1 ) AS canc,
left( name1, 5 ) AS left_name1,
length( kunnr ) AS leng_kunnr,
lower( name1 ) AS low_name1,
lpad( kunnr, 10, 'A' ) AS lpad_kunnr,
ltrim( kunnr, ' ' ) AS ltrim_kunnr,
replace( kunnr, '12', 'mn' ) AS replace_kunnr,
substring( name1, 6, 6 ) AS substr_name1,
upper( name1 ) AS upper_name1,
rpad( kunnr, 10, 'M' ) AS rpad_kunnr,
rtrim( kunnr, '3' ) AS rtrim_kunnnr
FROM @it_final AS final INTO TABLE @DATA(it_final1).

Concat: We can concatenate 2 (exactly 2 fields) into one field.


Left: From left side on wards it will pick mentioned number of characters.
Length: It will pick the size of that field
Lower: It will convert the value in lower case
LPAD: In total given length it will display the actual value, in remaining space from side on
wards it will display the mentioned letter.
LTRIM: we can remove something from left side .
Replace: Replace in the value as mentioned in the query
Substring: Pick particular length of data from the specified field
Upper: Covert the data to upper case
RPAD: In total given length it will display the actual value, in remaining space from right
side on wards it will display the mentioned letter
RTRIM: We can remove something from right side

28. Table Expression (change internal table value without work area)
Before 7.4
Before 7.4 this is not possible.

After 7.4
lt_kna1[ kunnr = '0010100002' ]-ort01 = 'Bangalore'.

सतीष कुमार रे ड्डि एम एन Page: 112


If the customer exist in the internal table, then it will not show any error. If we pass
invalid condition, then it will through dump. To avoid that one we can write like this.

TRY.
lt_kna1[ kunnr = '10100002' ]-ort01 = 'Bangalore' .
CATCH cx_sy_itab_line_not_found.
ENDTRY.

29. Switch Operator


Before 7.4
IF ls_vbak-vbtyp = 'A'.
lv_doc_type = 'Inquiry'.
ELSEIF ls_vbak-vbtyp = 'B'.
lv_doc_type = 'Quetation'.
ELSEIF ls_vbak-vbtyp = 'C'.
lv_doc_type = 'Order'.
ENDIF.

After 7.4
* data(lv_doc_type) = SWITCH #( ls_vbak-vbtyp when 'A' then 'Inquiry'
data(lv_doc_type) = SWITCH string( ls_vbak-
vbtyp when 'A' then 'Inquiry'
when 'B' then 'Quetation'
when 'C' then 'Order' ).
Here I’m mentioning like SWITCH STRING( ). If we don’t maintain ‘string’ here, it will
pick the first when condition data type and length for ‘lv_doc_type’. That is why I’ve
commented SWITCH #( ).

30. Loop in group by


Before 7.4
Before ABAP 7.4, we can use control break statements to achieve it.
LOOP AT LT_MAT INTO DATA(LS_MAT1).
DATA(LS_MAT) = LS_MAT1.
AT NEW MTART.
WRITE:/ LS_MAT-MATNR, LS_MAT-MTART, LS_MAT-MATKL.
ENDAT.
ENDLOOP.
In LT_MAT internal table, MTART is the first field. If we mentioned this field in second
column of the internal table, the values will come improperly because system will
consider first field and second field as a group.

After 7.4
lt_mat = VALUE #( ( matnr = '123' mtart = 'HALB' matkl = '001' )
( matnr = '124' mtart = 'ROH' matkl = '002' )
( matnr = '125' mtart = 'FERT' matkl = '006' )
( matnr = '126' mtart = 'ROH' matkl = '009' )
( matnr = '127' mtart = 'FERT' matkl = '001' )

सतीष कुमार रे ड्डि एम एन Page: 113


( matnr = '128' mtart = 'HALB' matkl = '003' )
( matnr = '129' mtart = 'ROH' matkl = '003' )
( matnr = '130' mtart = 'ROH' matkl = '004' ) ).

loop at lt_mat into data(ls_mat) GROUP BY ( mtart = ls_mat-mtart ).


write:/ ls_mat-matnr, ls_mat-mtart.
endloop.
Here we can keep the MTART in any where in the internal table, it will not consider any
other field. If we want to consider any other field, then we have mention that field in ‘group
by’.

If we want to loop the group / block, we can go like this.


LOOP AT lt_mat INTO DATA(ls_mat) GROUP BY ( key1 = ls_mat-
mtart index = GROUP INDEX size = GROUP SIZE ) INTO DATA(gb).
write:/ 'group index = ', gb-index.
write: 'group size = ', gb-size.
LOOP AT GROUP gb INTO DATA(gs).
WRITE:/ gs-matnr, gs-mtart.
ENDLOOP.
ENDLOOP.
31. Reduce Operator
Before 7.4
Before ABAP 7.4, there is no ‘Reduce’ concept.

After 7.4
TYPES: BEGIN OF ty_std,
name TYPE char20,
marks TYPE i,
END OF ty_std.
DATA lt_std TYPE TABLE OF ty_std.

lt_std = VALUE #( FOR i = 1 THEN i + 1 WHILE i <= 20


( name = | name { i } | marks = i ) ).
DATA(lv_sum) = REDUCE #( INIT x = 0 FOR wa IN lt_std where ( marks > 10
) NEXT x = x + wa-marks ).
Here we have used like
lt_std = VALUE #( FOR i = 1 THEN i + 1 WHILE i <= 20
( name = | name { i } | marks = i ) ).
I’m just passing the values to the internal table by using above statement. I’m using For in
the above syntax for variable ‘I’. Not required to declare this variable.
DATA(lv_sum) = REDUCE #( INIT x = 0 FOR wa IN lt_std where ( marks > 10
) NEXT x = x + wa-marks ).
Here ‘X’ is one variable. I’m initializing the value to X is as ‘0’. Then it will do calculate. If
we want remove the where condition we can remove it.

By default the ‘X’ variable will contain integer. If we want to convert with decimal, we can
write in this way.

सतीष कुमार रे ड्डि एम एन Page: 114


data(lv_netwr) = REDUCE #( INIT X type netwr
for wa_vbak in lt_vbak
next x = x + wa_vbak-netwr ).
Here declaring variable ‘X’ with data element NETWR. What is the data type and is there for
NETWR, those will apply for variable ‘X’.

32. Filter
Before 7.4
This option was not there before ABAP 7.4

After 7.4
data: lt_marc_all type STANDARD TABLE OF marc
with NON-UNIQUE SORTED KEY werks COMPONENTS werks,
lt_marc type STANDARD TABLE OF marc.

select * from marc into TABLE @lt_marc_all.


lt_marc = FILTER #( lt_marc_all EXCEPT USING KEY werks where werks =
'APL1' ).

While declaring the internal table, we need to maintain type of standard table and uniq or non
uniq key fields we need to declare. Other wise it will throw error.

33. Condense
Before 7.4
data(lv_name1) = condense( lv_name ).

After 7.4
data(lv_name) = ' XXShree Janani FoundatioXnn '.
data(lv_name1) = condense( lv_name ).
data(lv_name2) = condense( VAL = lv_name1 del = 'X' from = 'n' to = '2'
).
If we pass condense( variable_name), then it will remove the space at starting of the variable
value and at last of the variable value.
If we pass condense( VAL = lv_name1 del = 'X' from = 'n' to = '2' ).
It will remove the space at the starting and ending of the variable value. Del = ‘X’ means it
will remove ‘X’ character from the beginning and ending of the variable (if ‘X’ is available
at beginning and ending of that variable value.
From means it will check is there any letter (From value letter) in that variable, if it is there it
will replace with ‘To’ letter. (Here letters only will modify. Not words and sentences)

सतीष कुमार रे ड्डि एम एन Page: 115


34. Condition
Before 7.4
Before 7.4 there is no concept of condition

From 7.4
SELECT FROM vbak
FIELDS vbeln, kunnr, vbtyp, audat, CAST( ' ' AS CHAR( 30 ) ) AS date_stat,
CAST( ' ' AS CHAR( 30 ) ) AS ord_type
WHERE vbeln IN @s_vbeln
INTO TABLE @DATA(lt_vbak).

LOOP AT lt_vbak ASSIGNING FIELD-SYMBOL(<fs_vbak>).


<fs_vbak>-ord_type = COND #( WHEN <fs_vbak>-vbtyp = 'A' THEN 'Inquiry'
WHEN <fs_vbak>-vbtyp = 'B' THEN 'Quotation'
WHEN <fs_vbak>-vbtyp = 'C' THEN 'Order' ).

<fs_vbak>-date_stat = COND #( LET lv_date = '20170810' IN


WHEN <fs_vbak>-audat < lv_date THEN 'Old Order'
WHEN <fs_vbak>-audat > lv_date THEN 'New Order'
ELSE 'Today Order' ).
ENDLOOP.
In select query I’ve mentioned CAST( ' ' AS CHAR( 30 ) ). If we don’t mention CAST
here system will consider Ord_type field as char1. We need to increase the data length with
char30. So we are converting the length by using CAST.

‘LET’ is used to declare one variable in middle of program and we need to assign something
value to it.

35. Remove leading zeros


Before 7.4
call function 'CONVERSION_EXIT_ALPHA_OUTPUT'
exporting
INPUT = <FS_VBAK>-VBELN
importing
OUTPUT = <FS_VBAK>-VBELN.
After 7.4
<fs_vbak>-vbeln = |{ <fs_vbak>-vbeln ALPHA = OUT }|.

If we pass ALPAH = IN it will add leading zeros.

सतीष कुमार रे ड्डि एम एन Page: 116


Inline Declarations should not apply in the following cases

1. Right Hand Side of the assignment


data(num) = num + 1.
Here I’ve used DATA(NUM). System will not allow you to use that variable in the same
line.

2. In Function Module we can’t use inline declarations.

data(lv_matnr) = '123'
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_matnr
IMPORTING
OUTPUT = data(lv_matnr2).

If we declare Inline Declarations in Function Modules, it will though error.

3. Inline declaration are not global

PERFORM xyz.
PERFORM mno.

FORM xyz.
DATA(lv_kunnr) = '123'.
ENDFORM.

FORM mno.
DATA(lv_kunnr1) = lv_kunnr.
ENDFORM.

In ‘XYZ’ form, I’m declaring LV_KUNNR variable. We have to use it in that form only
we can’t use it in another form. If try to use it in out side of that form, it will through
error.

सतीष कुमार रे ड्डि एम एन Page: 117


सतीष कुमार रे ड्डि एम एन Page: 118
Hi friends....

Please read the bellow message whenever you are free.

Today we have food, clothes, shelter. Because of we are employees. But lot of people don’t
have these much of facilities. I mean orphan children, handicapped children, destitute
senior citizens are suffering with minimum facilities. A few children are begging in the bus
stops, platforms... a few people will left their old age parents at bus stops also. Orphan
homes or Old age home people take care of them. They are running their organizations
without providing the food three times per day. They can provide when they have fund. In
remaining days they may provide 1 time or 2 times per day.

We are providing food, clothes, medicine, shelter to the orphanages (depend on their
requirement). We started to give training on software courses to the students & for
unemployees with free of cost. We will upload the training videos in YouTube:
https://www.youtube.com/@sathishreddymn

If you want to join with us, you can call: 9866079202 / 8332999399

General Secretary
M N Sathish Kumar Reddy
Mail id: satishkumarreddy.mn@gmail.com
Mobile: 9866079202

सतीष कुमार रे ड्डि एम एन Page: 119


सतीष कुमार रे ड्डि एम एन Page: 120

You might also like