You are on page 1of 8

ABAP News for Release 7.

50 – Host and Other Expressions in Open


SQL
October 28, 2015 | 11,206 Views |

Horst Keller


more by this author
ABAP Development
abap

 share 0
 share
 tweet
 share

Follow RSS

After a long time of stagnation the development of Open SQL awoke from its deep slumber and took some major steps in
ABAP 7.40 in order to comprise as many features as possible from SQL92 and to offer about the same functionality as
the SELECT statement of the DDL of ABAP CDS. In order to do so, a new foundation for Open SQL was laid by introducing
a new SQL parser into the ABAP runtime environment. One consequence of this is the fact that Open SQL plays a bit other
role in ABAP than before. While before 7.40 Open SQL was regarded more a part of the ABAP language itself, meanwhile
the SQL character becomes more and more pronounced. One of the major indicatons for this is the new role of host variables.
Before 7.40, you used ABAP variables in Open SQL statements as it is done in all other ABAP statements. In fact, this
prevented further development quiet effectively. Open SQL statements are executed on the database after being transformed
to native SQL. In order to push down more sophisticated things than simple comparisons with ABAP variables
in WHERE conditions – say SQL expressions in many operand positions – the Open SQL parser must be able to distinguish
clearly between operands that are evaluated by the database and ABAP variables whose contents has to be passed to the
database. In order to fulfill this task, ABAP variables in Open SQL statements meanwhile fully play the role of host
variables as ABAP variables always did in static native SQL (EXEC SQL). You can and should prefix ABAP host variables
in Open SQL with @. In fact, you can use all the new SQL features introduced to Open SQL starting with Release 7.40 only if
you do so. Other fundamental changes that were introduced to Open SQL in order to make it fit for the future were comma
separated lists and placing the INTO addition of a SELECT statement behind the authentic SQL clauses.

As a first benefit of these measures, already with ABAP 7.40 fundamental new features in Open SQL were rolled out,
comprising SQL expressions in various operand positions or the possibilty of inline declarations. With ABAP 7.50 this
development is continued and this blog introduces some of the new features (more to come).

Host Expressions

In almost all positions where you could place host variables, including the operand positions of SQL expressions from 7.40 on
or the work areas of writing SQL statements, you can use host expressions now using the syntax

… @( abap_expression ) …
A host expression abap_expression can be any ABAP expression, that is a constructor expression, a table
expression, an arithmetic expression, a string expression, a bit expression, a builtin-function, a functional method,
or a method chaining inside parentheses () prefixed with @. The host expressions of an Open SQL statement are
evaluated from left to right and their results are passed to the database as it is done for the contents of host
variables. In fact you can see host expressions as short cuts for assignments of ABAP expressions to ABAP
helper variables and using those as host variables. The following example shows a table expression that reads a
value from an internal table carriers on the right hand side of a WHERE condition.

SELECT carrid, connid, cityfrom, cityto


FROM spfli
WHERE carrid =
@( VALUE spfli-carrid( carriers[ KEY name
carrname = name ]-carrid
OPTIONAL ) )
INTO TABLE @DATA(result).

I personally like the following:

DATA(rnd) = cl_abap_random_int=>create(
seed = CONV i( sy-uzeit ) min = 1 max = 100 ).
INSERT demo_expressions FROM TABLE @(
VALUE #(
FOR i = 0 UNTIL i > 9
( id = i
num1 = rnd->get_next( )
num2 = rnd->get_next( ) ) ) ).

An internal table is constructed and filled with random numbers inside an INSERT statement. A cool feature for the
ABAP documentation’s demo programs …

For more information see Host Expressions

SQL Expressions

With ABAP 7.50, the usage of SQL expressions was extended as follows:

 Besides using them in the SELECT list, you can use them as left hand sides of comparisons
withWHERE, HAVING, ON, and CASE and as Operands of a CAST expression. Note that this includes host variables
and host expressions as operands of SQL expressions.
 The following SQL functions can be used in SQL expressions
now: ROUND, CONCAT, LPAD, LENGTH, REPLACE, RIGHT, RTRIM, SUBSTRING. The COALESCE function can
have up to 255 arguments now.

As an example of an arithmetic expression on the left hand side of a WHERE condition see:

SELECT carrid, connid, fldate, seatsmax, seatsocc,


seatsmax – seatsocc AS seatsfree
FROM sflight
WHERE seatsmax – seatsocc > @( meth( ) )
INTO TABLE @DATA(result).
As an example for string functions see the following concatenation of columns into one column with CONCAT:

SELECT CONCAT( CONCAT( carrid,


LPAD( carrname,21,’ ‘ ) ),
LPAD( url,40,’ ‘ ) ) AS line
FROM scarr
INTO TABLE @DATA(result).

This concatenation is not possible with the operator && that is available since ABAP 7.40.

For more information see SQL Expressions.

Path Expressions

Path expressions are something you know from CDS already (duh!). If a CDS view exposes an association, the same or
another view can access it using a path expression.

For example, the following CDS view uses path expressions in its SELECT list:

@AbapCatalog.sqlViewName: ‘DEMO_CDS_USE_ASC’
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view demo_cds_use_assocs
with parameters p_carrid:s_carrid
as select from demo_cds_assoc_scarr as scarr
{ scarr.carrname,
scarr._spfli.connid,
scarr._spfli._sflight.fldate,
scarr._spfli._sairport.name }
where scarr.carrid = :p_carrid

The name of the associations are prefixed by an underscore _ and are defined in the following views:

@AbapCatalog.sqlViewName: ‘DEMO_CDS_ASC_CAR’
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view demo_cds_assoc_scarr
as select from scarr
association to demo_cds_assoc_spfli as _spfli
on scarr.carrid = _spfli.carrid
{ _spfli,
carrid,
carrname }

@AbapCatalog.sqlViewName: ‘DEMO_CDS_ASC_SPF’
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view demo_cds_assoc_spfli
as select from spfli
association to sflight as _sflight
on spfli.carrid = _sflight.carrid and
spfli.connid = _sflight.connid
association [1..1] to sairport as _sairport
on spfli.airpfrom = _sairport.id
{ _sflight,
_sairport,
carrid,
connid,
airpfrom }

With ABAP 7.50 Open SQL’s SELECT can also use such path expressions in its SELECT list or FROMclause when accessing
CDS views. The following Open SQL statement does the same as the first CDS view above:

SELECT scarr~carrname,
\_spfli-connid AS connid,
\_spfli\_sflight-fldate AS fldate,
\_spfli\_sairport-name AS name
FROM demo_cds_assoc_scarr AS scarr
WHERE scarr~carrid = @carrid
ORDER BY carrname, connid, fldate
INTO TABLE @DATA(result).

Looks not too different, eh? Only the dots have to be replaced by backslashes \ (and because of this, the path expressions
looks like those for meshes). When compiling such an Open SQL statement, the path expressions are converted to joins on the
database. Check it out with ST05.

For more information see Path Expressions.

More News

That’s not all about Open SQL in ABAP 7.50. In an upcoming blog I will show you an enhancement to SELECT that became
possible because the INTO clause can and should be placed at its end …

ABAP News for Release 7.50 – SELECT UNION


November 9, 2015 | 9,277 Views |

Horst Keller


more by this author
ABAP Development
abap

 share 0
 share
 tweet
 share

Follow RSS

I promised to tell you, why the INTO clause should be placed behind all the other clauses in an Open
SQL SELECT statement. One reason is that Open SQL also wanted to support the SQL syntax addition UNION.
An UNION addition can be placed between SELECT statements in order to create the union of the result sets. ABAP CDS
offered its UNION from the beginning (7.40, SP05). If you wanted to use it in Open SQL, you had to wrap it in a CDS view.
What hindered Open SQL? Well, the position of the ABAP specific INTO clause before the WHERE, GROUP BY and ORDER
BY clauses. These clauses can be part of any SELECT statement participating in unions and there must be only
one INTO clause at the end. Therefore, with 7.40, SP08, as a first step, the INTO clause was given a new position.
Now, with ABAP 7.50, we can bring the harvest in. Let me show you an example. The task is to get the names of all the
ABAP source texts of a package. These might be needed for searching in the sources or for dumping them in a file. All
programs can be found in the database table TRDIR. You know, that the source code files of some ABAP program types like
class pools and function pools are distributed over include programs. In order to select the correct technical names of the
include programs, it is not a bad idea to construct a ranges table that does the search for you based on some known features.
Before ABAP 7.50, the construction of such a ranges table might have looked as follows:
DATA prog_range TYPE RANGE OF trdir-name.

SELECT 'I' AS sign, 'EQ' AS option, obj_name AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'PROG' AND devclass = @devclass
INTO TABLE @prog_range.

SELECT 'I' AS sign, 'CP' AS option, obj_name && '*' AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'CLAS' AND devclass = @devclass
APPENDING TABLE @prog_range.
* Not perfect, from 7.51 on the following is better
*SELECT 'I' AS sign, 'CP' AS option, concat( rpad( obj_name, 30, '=' ), '*' ) AS low,
* ' ' AS high
* FROM tadir
* WHERE pgmid = 'R3TR' AND object = 'CLAS' AND devclass = @devclass
* APPENDING TABLE @prog_range.

SELECT 'I' AS sign, 'EQ' AS option, 'SAPL' && obj_name AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'FUGR' AND devclass = @devclass
APPENDING TABLE @prog_range.

SELECT 'I' AS sign, 'CP' AS option, 'L' && obj_name && '+++' AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'FUGR' AND devclass = @devclass
APPENDING TABLE @prog_range.

Four individual SELECT statements are used to fill one internal table prog_range with the help of
the APPENDING addition. Note the usage of string expressions in the SELECT lists.
With ABAP 7.50 you can pack the four SELECT statements into one (this can be called code push down):
DATA prog_range TYPE RANGE OF trdir-name.
SELECT 'I' AS sign, 'EQ' AS option, obj_name AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'PROG' AND devclass = @devclass
UNION
SELECT 'I' AS sign, 'CP' AS option, obj_name && '*' AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'CLAS' AND devclass = @devclass
*Not perfect, from 7.51 on the following is better
*SELECT 'I' AS sign, 'CP' AS option, concat( rpad( obj_name, 30, '=' ) , '*' ) AS low,
* ' ' AS high
* FROM tadir
* WHERE pgmid = 'R3TR' AND object = 'CLAS' AND devclass = @devclass
UNION
SELECT 'I' AS sign, 'EQ' AS option, 'SAPL' && obj_name AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'FUGR' AND devclass = @devclass
UNION
SELECT 'I' AS sign, 'CP' AS option, 'L' && obj_name && '+++' AS low, ' ' AS high
FROM tadir
WHERE pgmid = 'R3TR' AND object = 'FUGR' AND devclass = @devclass
INTO TABLE @prog_range.
The result is the same as above and can be used to get the program names, e.g. as follows:
SELECT name
FROM trdir
WHERE name IN @prog_range
ORDER BY name
INTO TABLE @DATA(programs).
(The example is not bullet-proof, but well an example and you might extend it…)

As shown here, with UNION you can unite the result sets from SELECT statements for one database table, but it is also
possible to combine the result sets of different database tables, if the numbers of columns and the column types match.
For more information and examples see SELECT – UNION.

ABAP News for Release 7.50 – INSERT FROM Subquery and GTTs
November 18, 2015 | 4,053 Views |

Horst Keller


more by this author
ABAP Development
abap

 share 0
 share
 tweet
 share

Follow RSS

This is about two (no, even three) new things in Open SQL in ABAP 7.50.
INSERT FROM Subquery
Before ABAP 7.50, you can use subqueries in the WHERE condition of SELECT, UPDATE, or DELETE of Open SQL.
With ABAP 7.50, there is a new position for a subquery in Open SQL: Behind FROM of statement INSERT. This can help
you to avoid unnecessary round trips of aggregated data between database and application server. I simply show you
the example from the documentation:
Before 7.50: INSERT FROM TABLE
SELECT
FROM scarr AS s
INNER JOIN spfli AS p ON s~carrid = p~carrid
FIELDS s~mandt,
s~carrname,
p~distid,
SUM( p~distance ) AS sum_distance
GROUP BY s~mandt, s~carrname, p~distid
INTO TABLE @DATA(temp).

INSERT demo_sumdist_agg FROM TABLE @temp.


The task is to aggregate some data from two tables and insert them into another table. Before ABAP 7.40 you aggregated into
an internal table temp and inserted that table into the target table. For that the aggregated data were transported from the
database to the application server and back again.
With 750: INSERT FROM SELECT
INSERT demo_sumdist_agg FROM
( SELECT
FROM scarr AS s
INNER JOIN spfli AS p ON s~carrid = p~carrid
FIELDS s~carrname,
p~distid,
SUM( p~distance ) AS sum_distance
GROUP BY s~mandt, s~carrname, p~distid ).
Isn’t that simple? Same SELECT statement as above but placed directly as a subquery in parentheses behind
addition FROM of INSERT. Only one SQL statement. No transport of the aggregated data from the database to the application
server and back again. Don’t have to say more here, or? For more information see INSERT dbtab – subquery.

Intermission: SELECT FROM FIELDS


Did you notice the new FIELDS addition in SELECT? The FIELDS addition allows you to place the FROMclause directly
behind SELECT and in front of all other clauses. To do so, the SELECT list has to be placed behind FIELDS. Why that new
sequence? A FROM clause in front of all other clauses supports tools like code completion and syntax coloring in all clauses.
Compare to SELECT in ABAP CDS. Same there, but with curly brackets instead of FIELDS.

GTTs
Now imagine that you need the aggregated data of table demo_sumdist_agg only within one DB transaction (DB LUW). A
normal database table is too heavy weighted for such temporary data because an database’s administration of a normal table
supports persistent data. Therefore databases support the concept of Global Temporary Tables (GTTs). A GTT is database
table with a light weight administration that is bound to one DB transaction: A GTT is always empty at the start of a DB
transactionand must be empty at the end of each DB transaction.
Database systems support GTTs natively.
With ABAP 7.50, you can also define GTTs in the ABAP Dictionary by setting the Table Category to Global
Temporary Table.

Then, the underlying database behaves accordingly. When accessing a GTTdefined in the ABAP Dictionary with Open SQL,
the following additional rules apply:

 If you modify the contents of a GTT with Open SQL statement, you must delete it explicitly before the end of the
current database LUW either by the Open SQL statement DELETE FROM dbtabwithout a WHERE condition or with
an explicit database commit or database rollback (then the database interface deletes the contents).
 If the contents of a GTT filled with Open SQL is not deleted explicitly before an implicit database commit, the
runtime error COMMIT_GTT_ERROR occurs independently of the actual content (even it is empty).

Why that special behavior?

 Comprehensibility: A database system deletes the contents of a GTT at the end of the database LUW. A developer
might be surprised to find a table empty after an implicit database commit (a simple WAIT statement suffices).
Therefore, Open SQL forces explicit deletion.
 Platform dependency: It cannot be guaranteed that every database platform deletes the data in a GTT before an
implicit database commit.

For our above example, this means: If demo_sumdist_agg is a GTT (it isn’t in 7.50 SP01, but I changed it into a GTT for
SP02 during writing that blog) you must include
DELETE FROM demo_sumdist_agg.
before any implicit database commit as e.g. before calling a dynpro screen. Otherwise the above runtime error occurs (and I
had to adjust my examples that access the table).

For more information and examples see Global Temporary Tables.

You might also like