Beruflich Dokumente
Kultur Dokumente
These are kind of functions which essentially are make or break. They are
not flexible enough to give you a third option. Simply put they return
LOGICAL or BOOLEAN result.
1. Numeric Functions
Smallest integer
Hitting the Ceiling of the Floating number not less
CEIL(arg)
Number. than the value of
arg
Rounding the
Designated
ROUND(arg, pos) Rounded value of arg.
decimal point
value
2. Below code snippet on ABS, CEIL, FLOOR, DIV, DIVISION, MOD and
ROUND should help you understand the concept better.
@AbapCatalog.sqlViewName: 'ZFLIGHT_SCH_V'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Built In Functions'
define view ZFLG_FNC_DDL as select distinct from sflight as a
{
abs(-2) as Abs_Op,
/*Division*/
div(5,3) as Div_Op,
division(5,3,5) as Div_Op2,
mod(5,3) as Mod_Op,
a.price as Flg_Price,
round( a.price,1) as Round_Op
}
Please check each output. Did you notice Ceil is 26 for a number 25.3 while
Floor is 25 for the same number 25.3.
2. String Functions
@AbapCatalog.sqlViewName: 'ZSTR_FN_V1'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Built In Functions'
define view ZFNC_DDL as select distinct from makt as a
{
key a.matnr as Mat_Num,
a.maktx as Mat_Desc,
length( a.maktx ) as Des_Len,
instr( a.maktx, 'est' ) as Des_Find,
concat( a.maktx, a.spras ) as Des_Con,
concat_with_space( a.maktx, a.spras, 2 ) as Des_Con_space,
left( a.maktx, 3 ) as Des_left,
lower( a.maktx ) as Des_lower
}
Part 1 of Strings:
Function Description
Now, wondering where are the complementing string functions??? They are
below.
@AbapCatalog.sqlViewName: 'ZSTR_FN_V1'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Built In Functions'
define view ZFNC_DDL as select distinct from makt as a
{
key a.matnr as Mat_Num,
a.maktx as Mat_Desc,
right( a.maktx, 5 ) as Des_right,
/*For Strings */
lpad( a.maktx, 6, 'xx' ) as Des_lpad,
rpad( a.maktx, 6, 'y' ) as Des_rpad,
ltrim( a.maktx, 't' ) as Des_ltrim,
rtrim( a.maktx, 't' ) as Des_rtrim,
replace( a.maktx, 'est','ough' ) as Des_replace,
substring( a.maktx, 2, 1 ) as Des_substring,
upper( a.maktx ) as Des_upper
}
Check how conveniently you can play around with the strings using lpad,
rpad, ltrim, rtrim, replace, substring, upper etc. They come really handy in
actual projects.
ABAPers !!! How on this earth can we forget our traditional methods working
with Conversion FMs ??? Isn’t it???
Well, those are replaced by Padding and Trimming – Both sides Left and
Right.
Function Description
Points to Remember:
Example:
define view ZFLG_FNC_DDL as select distinct from sflight as a
{
key a.connid as Flg_Connid,
/*For Numericals */
lpad( a.connid, 6, '22' ) as Flg_lpad,
rpad( a.connid, 6, '99' ) as Flg_rpad,
ltrim( a.connid, '0' ) as Flg_ltrim,
a.fldate as Flg_Date,
rtrim( a.fldate, '8' ) as Flg_rtrim
}
Bonus Segment:
Requirement : “Change the data retrieved for Flight Time from Total
Minutes to Hours:Minutes Format”
How about complicating our lives? Actually, it may be the way to simplify.
Let’s give a try.
@AbapCatalog.sqlViewName: 'ZFLIGHT_SCH_V'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Built In Functions'
define view ZFLG_FNC_DDL as select from spfli as a
left outer join sgeocity as b
on a.cityfrom = b.city
{
key b.city as Source,
key b.city as Destination,
key a.carrid as Flg_ID,
key a.connid as Flg_Conn,
a.fltime as Flg_Time
}
Functions can be handy here…Check out the code below which would suffice
our requirement.
@AbapCatalog.sqlViewName: 'ZFLIGHT_SCH_V'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Flight Schedule Details'
define view ZFLG_FNC_DDL as select from spfli as a
left outer join sgeocity as b
on a.cityfrom = b.city
{
key b.city as Source,
key b.city as Destination,
key a.carrid as Flg_ID,
key a.connid as Flg_Conn,
concat( concat(lpad ( ltrim ( cast( div(a.fltime, 60) as abap.char( 12 ) ), '0' ), 2, '0' ), ':'
),
lpad ( ltrim ( cast( mod(a.fltime, 60) as abap.char( 12 ) ), '0'), 2, '0' ) ) as Flg_Time
}
The above one line string function is just an example of how you can play
around with any requirement. Break the code from center and go outward. It
is self-explanatory.
Seldom we see these being used. But then application of knowledge should
not be seldom.
As the name says, the currency of the amount/price field is converted from
source (as stored at the database) currency to end user/input currency.
Now, let’s give two target currencies. First USD and other INR.
There is some absurd and strange thing. Let’s apply some common sense. The exchange rates
keep fluctuating as a pendulum of the clock. I gave a future exchange date (Note : 31-01-
2019).
Astonishing as it may sound, SAP has been able to predict even the market
exchange price for a FUTURE DATE (31-01-2019 on Jan 28, 2019) !!! Not
sure how it is getting picked. Anyone who is aware please comment and let
us and the rest of the world know.
Some background. For certain currencies like JPY, HUF, KRW, COP there is
a difference how the external world stores value than internal.
In TCURX table, JPY is set with 0 decimal. EUR doesn’t exist in the table, that
is, default to 2 decimal.
@AbapCatalog.sqlViewName: 'ZDEC_SHFT_V'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: false
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Test Currency Conversion'
define view ZDEC_SHFT
with parameters p_amt : abap.curr( 5, 2 )
as select distinct
from sflight as a{
key a.carrid as FlgID,
key a.connid as FlgConID,
key a.fldate as FlgDat,
a.currency,
decimal_shift( amount => :p_amt, currency => a.currency ) as DEC_SHFT
}
From the above two pictures it is quite evident that the input : 21.34 was
interpreted differently in accordance with the corresponding currencies.
We would like to end this article here. Yes, we know, we promised four
points. For the last bullet point, we would prepare a detailed tutorial on Date
and Time Functions in our next blog. So, please stay tuned.
Till then enjoy your new found love in the form of ABAP Programming for
S/4HANA and tune back to us for some explanation or the curious currency
conversion function.
DAY, MONTH and YEAR. We are limiting our discussion to first two in this
article. Let’s get started.
1. ADD DAYS
2. ADD MONTHS
3. DAYS BETWEEN TWO DATES
4. DATE VALIDATION
1. ADD DAYS:
Do you recall? There are some numbers on either side of the great “0” on
number line, called as INTEGERS. That’s the hint to define ADD_DAYS in CDS
Views.
Yes, absolutely. ADD_DAYS can be used not just for adding but also
SUBTRACTING.
Straight forward with three parameters. One each for input date,
number of months to be added and error handling respectively.
Don’t be smart here. Never calculate the days between two DATES. It
can ruin your day.
Back to CDS, two inputs, one for first extreme and other for other
extreme.
4. DATE VALIDATION
What more can you ask, this can be used to validate the date and
know whether your DATE was valid ( if not, just WISH to have another
) or NOT.
For all the above functions ONE Code Example is used. But to provide
an enthralling and excruciating experience, we have MORE than ONE
Test Case.
CODE SNIPPET:
@AbapCatalog.sqlViewName: 'ZDT_TIME_FN_V'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Test Date and Time'
define view ZDT_TIME_FN
with parameters p_add_days : abap.int4,
p_add_months: abap.int4,
@Environment.systemField: #SYSTEM_DATE
p_curr_date : abap.dats
as select from sflight as a {
key a.carrid as FlgId,
key a.connid as FlgConnId,
key a.fldate as FlgDate,
dats_add_days (a.fldate, :p_add_days , 'INITIAL') as Added_DT,
dats_add_months (a.fldate, :p_add_months, 'NULL' ) as Added_MT,
dats_days_between (a.fldate, $parameters.p_curr_date ) as Days_BTW,
dats_is_valid (a.fldate) as Is_Valid
}
Very
IMPORTANT : Observe that parameter “P_CURR_DATE” does not have an asterisk. Me
ans that it is not a mandatory to provide . Then we have two ways to deal. One leave blank
and other to forcefully provide a date. Second case has been dealt in next example.
Wondering why the “-735740” was given in P_ADD_DAYS …..There is
something called as BVA in Software Testing…Go and check it out for
yourself what does that mean.
Now then….Let it be loud and clear there is a BUUUGGG !!! Second consecutive time we
are proud to point out that SAP cannot be foolproof. Look closely. We should have ideally
got INVALID.
Now, let’s analyse what we have done:
BONUS SEGMENT:
(the special segment which we promised above) .. disappointed?
In continuation with the previous topic, in this section we will explore two
more functions.
5. DATS_TIMS_TO_TSTMP
First input is date, second is time, third timezone, fourth client and finally
error handling.
6. TIMEZONE
Straight as an arrow, just pass the session client and get system’s Time
Zone.
TEST CASE 3:
@AbapCatalog.sqlViewName: 'ZDT_DT_TIME_FN_V'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Test Date and Time 2'
define view ZDT_DT_TIME_FN
with parameters @Environment.systemField: #SYSTEM_DATE
p_curr_date : abap.dats
as select from sflconn as a{
key a.agencynum as FlgAgy,
key a.flconn as FlgCon,
a.arrtime as FlgArr,
abap_system_timezone( $session.client,'NULL' )
as MyTimeZone
}
As usual we need test and validate. It has become a custom which can be
broken, but I will refrain
VALIDATION:
Time was picked from the database table. However, date was system date.
Literals
Other name Constants. They are of Two kinds viz Numeric and Character.
VIP (Very Important Point) – ALIAS play a very important role while we
create Associations between different CDS Views/Database Tables.
Parameters
Anything that a user is expected to provide as input to CDS, qualifies as a
parameter. Remember that CDS is PARAMETERISED!!!
Session variables
ABAPer’s blood sample will surely have “SY-SUBRC”, a system variable.
SAP is very strict, diktat is like “The variable is case-sensitive.
$session.vname, $Session.Vname, and $SESSION.VNAME can all be used. No
other spellings are allowed.” Same goes with CDS, session variables.
Following are examples:
Variable Usage
user Current user name, nominal value of the ABAP system field sy-uname
Current client. The default value is the nominal value of the ABAP
system field sy-mandt. In reads with an Open SQL statement (with the
client statement USING CLIENT) and in calls of an AMDP method from
ABAP (in whose declaration the addition AMDP OPTIONS CDS
SESSION CLIENT is specified), the value specified here.
Case distinction
Self Explanatory. Following can give you an idea :
1
2 Simple case distinction1. ... CASE operand
3 WHEN operand1 THEN result1
4 [WHEN operand2 THEN result2]
5 ...
6 [ELSE resultn]
7 END ...Complex case distinction2. ... CASE WHEN cond_expr1 THEN result1
8 [WHEN cond_expr2 THEN result2]
9 [WHEN cond_expr3 THEN result3]
10 ...
11 [ELSE resultn]
12 END ...
Conditions
Well, Well, this is interesting. The logical way of coding. How ?
Only two possible results – TRUE or FALSE. RIGHT or WRONG.
ABAP_TRUE or ABAP_FALSE. UNDERSTAND or DONT UNDERSTAND.
Operator True if
lhs <> rhs Value of lhs is not equal to the value of rhs
lhs < rhs Value of lhs is less than the value of rhs
lhs > rhs Value of lhs is greater than the value of rhs
lhs <= rhs Value of lhs is less than or equal to the value of rhs
lhs >= rhs Value of lhs is greater than or equal to the value of rhs
1
2 "... lhs >= rhs1 AND lhs <= rhs2 ... ".
1
2 ... lhs LIKE rhs [ESCAPE esc]...
1
2 .... lhs IS [NOT] NULL ...
1
2 @AbapCatalog.sqlViewName: 'ZFLG_CDS_OP_V'
3 @AbapCatalog.compiler.compareFilter: true
4 @AccessControl.authorizationCheck: #NOT_REQUIRED
5 @EndUserText.label: 'Operations'
6 define view ZFLG_CDS_OP
7 with parameters p_date : abap.dats
8 as select from sflight as a
9 {
10 key a.carrid as FlgCarr,
11 key a.connid as FlgConn,
12 key case ( a.planetype )
13 when '737-400' then 'BOEING'
14 when 'A340-600' then 'AIRBUS'
15 else 'OTHERS'
16 end as FlgType,
17 key a.fldate,
18 case
19 when a.price is null then 'error'
20 when a.price < 200 then 'Budget'
21 when a.price >= 200 and
22 a.price < 400 then 'Business'
23 else 'Very Costly'
24 end as flight_type,
25 $session.system_language as Language
26 }
27 where a.fldate = $parameters.p_date;
**Not Marked in the above screenshot. Literals, Alias. Please search them.
Provide the date. I knew it before hand.. I had already run my code without
parameter.
Result :
Following need a lot of emphasis and examples.
Arithmetic expressions
Aggregate expressions
Type Casting
1. Arithmetic Expression
Straight Forward. Addition/Subtraction/Multiplication/Division. Let’s
recall BODMAS rule which you learned in your elementary school.
Period.S o WHAT’S new ???
2. Aggregate Expressions
Let’s check what is there in store for us in this part of the story.
2 @AbapCatalog.sqlViewName: 'ZFLG_CDS_OP_V'
3 @AbapCatalog.compiler.compareFilter: true
4 @AccessControl.authorizationCheck: #NOT_REQUIRED
5 @EndUserText.label: 'Operations'
8{
14 count( * ) as TotalCount
15 }
GROUP BY
Hope you have some idea now, why we need Group By.
Back to example. I modified adding group by ‘CARRID’. Meaning we shall be
finding all the Aggregate Function value for each ‘CARRID’.
2 @AbapCatalog.sqlViewName: 'ZFLG_CDS_OP_V'
3 @AbapCatalog.compiler.compareFilter: true
4 @AccessControl.authorizationCheck: #NOT_REQUIRED
5 @EndUserText.label: 'Operations'
8{
14 count( * ) as TotalCount
15 } group by a.carrid
16
Now let’s see the initial output:
i) All the Key fields defined in the CDS needs to be part of Group By
Clause.
I included another field ‘CONNID’ as a key field and see the difference.
2 @AbapCatalog.sqlViewName: 'ZFLG_CDS_OP_V'
3 @AbapCatalog.compiler.compareFilter: true
4 @AccessControl.authorizationCheck: #NOT_REQUIRED
5 @EndUserText.label: 'Operations'
14 count( * ) as TotalCount
We see that now the aggregate functions behave differently, because all
calculations are done by first picking Carrier ID and then Connection ID.
Please note the total count is 26 in both cases for Flight Carrier ‘AA’.
Similarly the total count is 39 for Flight Carrier ‘DL’.
1
2 @AbapCatalog.sqlViewName: 'ZFLG_CDS_OP_V'
3 @AbapCatalog.compiler.compareFilter: true
4 @AccessControl.authorizationCheck: #NOT_REQUIRED
5 @EndUserText.label: 'Operations'
6 define view ZFLG_CDS_OP
7 as select from sflight as a
8{
9 key a.carrid as FlgCarr,
10 key a.connid as FlgConn,
11 max( a.price ) as MaxPrice,
12 min( a.price ) as MinPrice,
13 avg( a.price ) as AvgPrice,
14 sum( a.price ) as SumPrice,
15 count( * ) as TotalCount
16 } group by a.carrid, a.connid
17 having a.carrid = 'AA'
abap.clnt[(3)] CLNT
abap.dats[(8)] DATS
abap.fltp[(16,16)] FLTP
abap.int1[(3)] INT1
abap.int2[(5)] INT2
abap.int4[(10)] INT4
abap.int8[(19)] INT8
abap.lang[(1)] LANG
abap.raw(len) RAW
abap.sstring(len) SSTRING
abap.tims[(6)] TIMS
abap.unit( len ) CHAR with length len
Authorizations in CDS Views
Access Control or Authorization in another dimension worth mention
when it comes to SAP ABAP CDS (Core Data Services). Let’s see what is
on offer in CDS (exiting feature) which gives us an opportunity to explore the
options available to limit the access.
Are you new to CDS? Check Frequently Asked Questions in CDS View for
Beginners.
definitions, excuse me )
GRANT: Used for providing any user access privileges or other privileges for
the database operations.
For now, we shall concentrate only about ABAP CDS View Authorization.
Getting our hands dirty is the way forward. Following steps will give an
experience of how DCL, elder brother of SQL can protect DDL, his younger.
STEP 1: Simple Sample CDS View was created with join between SFLIGHT
and SFLCONNPOS.
1
2 @AbapCatalog.sqlViewName: 'ZCDS_ACCNTRL_DDL'
3 @AbapCatalog.compiler.compareFilter: true
4 @AccessControl.authorizationCheck: #NOT_REQUIRED
5 @EndUserText.label: 'CDS to Test Access Control'
6 define view ZCDS_TEST_ACCESS_CTRL as
7 select from sflight as a
8 inner join sflconnpos as b
9 on a.carrid = b.carrid
10 {
11 key a.carrid as MyFlightCarrier,
12 b.agencynum as MyAgencyNumber
13 }
Also Read: Write your first Program in S/4HANA.
STEP 2: Follow the below to create a DCL object for CDS View.
By default the following screen appears once you finish creating [good
feature by Eclipse for lazy people (like me) so that we don’t code]
What we noticed (from experience) is that we have 3 approaches available
for us to utilize. Do not worry, each of it has been covered below.
Approach 1 : Using just the View Name [Smarter people say Full
Access]
No Restrictions apply here. Just go and just provide your CDS View Name.
Nothing much to tell other than that WARNING !!!
It is best seen from the below description I got from the editor :
This warning tells that the User (ABAP developer) has not been mapped to
this DCL.
What we can infer is that the above approach 1 is somewhat not much useful
for us. Thus, let’s fast forward to Approach 2.
Before we deep dive, let’s see that data preview of the CDS Views:
The result set has entries for the following Flight Carriers:
Amused how I got it ??? Follow this : Right Top Corner of Data Preview ->
Add Filter -> Click on MyFlightCarrier -> Click on ” … ” -> Voila you got it !!!
Now if you are still not exhausted, continue to make a change in DCL.
Do the following:
Code Snippet :
1
2 @EndUserText.label: 'role_label'
3 @MappingRole: true
4 define role role_name {
5 grant select on ZCDS_TEST_ACCESS_CTRL
6 where MyFlightCarrier = 'DL' ;
7 }
Run Data Preview to see the Magic (well not really, you wrote the code and
Before you begin this, I suggest you to have a look on what is PFCG for some
important information.
But, more importantly for us is T-Code SU21. Navigate to find Auth Object
S_CARRID (as shown below with details).
All said and done. Now question remains, what have we achieved here?
Nothing. Why? That’s because we have not mapped our user ID
exclusively for this authorization object.
Conclusions:
There are other possibilities other than above three approaches namely,
Code :
1
2 @EndUserText.label: 'role_label'
3 @MappingRole: true
4 define role role_name {
5 grant select on ZCDS_TEST_ACCESS_CTRL
6 where ( MyFlightCarrier ) = <span class="token keyword">aspect</span> pfcg_auth
7 <span class="token punctuation">(</span>s_carrid<span class="token
punctuation">,</span> carrid<span class="token punctuation">,</span> actvt=<span
class="token string">'03'</span><span class="token punctuation">)</span> <span
class="token keyword">and</span>
MyFlightCarrier = 'LH' ;
CDS View :
1
2 @AbapCatalog.compiler.compareFilter: true
3 @AbapCatalog.sqlViewName: 'ZCDS_ACCNTRL_DDL'
4 @AccessControl.authorizationCheck: #CHECK
5 @EndUserText.label: 'CDS to Test Access Control'
6 define view ZCDS_TEST_ACCESS_CTRL as
7 select from sflight as a
8 inner join sflconnpos as b
9 on a.carrid = b.carrid
10 {
11 key $session.user as MyName,
12 key a.carrid as MyFlightCarrier,
13 b.agencynum as MyAgencyNumber
14 }
DCL :
1
2 @EndUserText.label: 'role_label'
3 @MappingRole: true
4 define role role_name {
5 grant select on ZCDS_TEST_ACCESS_CTRL
6 where MyName ?= aspect user; }
We can have multiple DCL for same CDS views. Try it.
Note: Use same CDS view name in all DCL sources, but have different role
names.
SEGW is the t-code to create OData Projects and eventually publish an
OData Service.
But would you not be surprised if we say, you can create your OData Projects
without going to SEGW transaction? Today, we would show you how you can
expose CDS View as OData Services with just some Annotations (i.e
SQL code).
Introduction
We have substantially explored the CDS views with major functionalities.
CDS provides another magical strength to the users to expose the views as
OData services. There is a conventional way to create a service in SEGW
importing the view you created.
Technical Environment
For CDS views we have used Eclipse Luna.
OData version 2 has been used for gateway application.
Step – I :
Create a view with a left outer join between tables VBAP and MARA. We have
considered VBAP as ‘soitem’ and MARA as ‘prod’. A left outer join between
two will allow you to select any fields from these two tables. For simplicity,
we took only the fields mentioned in the key.
Fig.1-Create First View
Step – II :
Create a second view with Association. Associations in CDS views are more
like associations in Gateways. You create an association to conceptually
join or associate one data source to a target data source on a
condition provided. If data sources can be envisaged as Entities of OData
service then associations are joining two entities conceptually.
Fig.2- Create view with Association and OData Annotation
Take special note of the Annotation at the 6th line: @OData.publish: true.
Step – III :
Now our view is ready. With the DDL view we should be able to see data
from Header table VBAK, Item table VBAP and Product table MARA.
Fig.3- DDLS view
Fig.3- Data from the view
Step – IV :
Note, once you activate the view you will be able to see an icon beside the
annotation (6th line) “@OData.Publish: true” which reads that you need to
register the service through /IWFND/MAINT_SERVICE.
Fig.4- OData Exposure in View
Step – V :
Now, as instructed go to transaction /IWFND/MAINT_SERVICE in the gateway
system to register the service created through CDS.
Fig.5- Find Service in /IWFND/MAINT_SERIVCE
Step – VI :
Once the service is found, click on the service to register and save it in the
appropriate package. Note we have not used SEGW to create any
service. This service got automatically generated due to OData
Annotation maintained.
Limitations
Please also be informed that this service can only provide GET operation.
No other CRUD operations can be done with this CDS view OData Exposure.
Usually, CDS views are created for fetching data (GET operations) and
therefore even with the above limitation, this method of exposing CDS views
as OData service is very helpful. This also shows the power of Annotations
(New SQL) in the Core Data Services.