From 716cb73570cb56becd176f7b0184d2e978eb0025 Mon Sep 17 00:00:00 2001 From: danrega <16720986+danrega@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:46:02 +0200 Subject: [PATCH] Update --- 03_ABAP_SQL.md | 2262 ++++++++++++++++++++++++++++-------------------- 1 file changed, 1306 insertions(+), 956 deletions(-) diff --git a/03_ABAP_SQL.md b/03_ABAP_SQL.md index 056d2cf..0a5e623 100644 --- a/03_ABAP_SQL.md +++ b/03_ABAP_SQL.md @@ -5,26 +5,31 @@ - [ABAP SQL](#abap-sql) - [Introduction](#introduction) - [Excursion: Database Tables and Views](#excursion-database-tables-and-views) - - [Reading Data Using SELECT](#reading-data-using-select) + - [Retrieving Data Using SELECT](#retrieving-data-using-select) - [Basic Syntax](#basic-syntax) - - [Using SELECT for Multiple Purposes](#using-select-for-multiple-purposes) - - [Clause Variations and Additions in SELECT Statements](#clause-variations-and-additions-in-select-statements) - - [More Clauses](#more-clauses) - - [Operands and Expressions in ABAP SQL Statements](#operands-and-expressions-in-abap-sql-statements) - - [SQL Operands](#sql-operands) - - [SQL Expressions](#sql-expressions) - - [Elementary Expressions](#elementary-expressions) - - [Numeric Functions](#numeric-functions) - - [String Functions](#string-functions) - - [Special Functions](#special-functions) - - [Aggregate Expressions](#aggregate-expressions) - - [Arithmetic, Cast, String Expressions, and Case Distinctions](#arithmetic-cast-string-expressions-and-case-distinctions) - - [Window Expressions](#window-expressions) - - [coalesce Function](#coalesce-function) - - [SQL Conditions](#sql-conditions) + - [SELECT List Variants](#select-list-variants) + - [Retrieving Single and Multiple Rows](#retrieving-single-and-multiple-rows) + - [Miscellaneous Options Regarding the Result](#miscellaneous-options-regarding-the-result) + - [Additional Clauses](#additional-clauses) - [Selecting Data by Evaluating the Content of Other Tables](#selecting-data-by-evaluating-the-content-of-other-tables) - - [Combining Data of Multiple Database Tables](#combining-data-of-multiple-database-tables) - - [Common Table Expressions (CTE)](#common-table-expressions-cte) + - [Combining Data of Multiple Tables](#combining-data-of-multiple-tables) + - [Common Table Expressions (CTE)](#common-table-expressions-cte) + - [SQL Conditions](#sql-conditions) + - [SQL Operands](#sql-operands) + - [SQL Expressions](#sql-expressions) + - [Elementary SQL Expressions](#elementary-sql-expressions) + - [Arithmetic Expressions](#arithmetic-expressions) + - [Cast Expressions](#cast-expressions) + - [String Expressions](#string-expressions) + - [Case Expressions](#case-expressions) + - [Aggregate Expressions](#aggregate-expressions) + - [Window Expressions](#window-expressions) + - [Null Expressions](#null-expressions) + - [Built-In SQL Functions](#built-in-sql-functions) + - [Numeric Functions](#numeric-functions) + - [String Functions](#string-functions) + - [coalesce Function](#coalesce-function) + - [More Functions](#more-functions) - [Changing Data in Database Tables](#changing-data-in-database-tables) - [Using INSERT](#using-insert) - [Using UPDATE](#using-update) @@ -135,11 +140,11 @@ Views](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm

⬆️ back to top

-## Reading Data Using SELECT +## Retrieving Data Using SELECT ### Basic Syntax -You use ABAP SQL `SELECT` statements to read data from one or more database tables (or views). This can be done to create a multirow or single row result set by assigning the result set to a suitable data object, i. e. you can store the multirow read result in an internal table or the single row result in a structure. +You use ABAP SQL `SELECT` statements to retrieve data from one or more data sources (such as database tables, views or internal tables). This can be done to create a multirow or single row result set by assigning the result set to a suitable data object, i. e. you can store the multirow read result in an internal table or the single row result in a structure. The `SELECT` statement includes several clauses that serve different purposes. The following code snippet shows the basic syntax (see the note below for a different but interchangeable syntax): ``` abap @@ -164,11 +169,11 @@ SELECT FROM source "What database table or view to read from > ``` abap > SELECT FROM dbtab > FIELDS comp1, comp2, comp3 ->    ... +> ... > > SELECT comp1, comp2, comp3 > FROM dbtab ->    ... +> ... > ``` >- Regarding the target into which data is read: Instead of using a variable that is (extra) declared beforehand, you can also make use @@ -181,117 +186,11 @@ SELECT FROM source "What database table or view to read from processing the internal table entries. Find more information in the ABAP cheat sheet [Internal Tables](01_Internal_Tables.md). The declaration operator [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) can be used to declare immutable variables. >- Many syntax examples in this cheat sheet show a selection from `dbtab` denoting a database table as a source. However, other data sources can also be specified. +>- The syntax options for the `SELECT` statement are extensive. Make sure that you consult the ABAP Keyword Documentation for all available options. The cheat sheet and snippets demonstrate a selection.

⬆️ back to top

-### Using SELECT for Multiple Purposes - -**Reading a single row into a structure** -``` abap -"SINGLE addition -"Here, all fields of a single row a read. Specifying an -"asterisk * indicates that all fields are to be read. -"Alternatively, you can list all the fields separated by comma. -"Note that if the selection covers more than one row, e. g. in case -"of a non-unique WHERE clause, one of these rows is included in -"the result. -SELECT SINGLE FROM dbtab - FIELDS * - WHERE ... - INTO @struc. "Existing structure of dbtab's row type - -"Reading a selected set of fields of a single row -SELECT SINGLE FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE ... - INTO @DATA(struc2). "Structure declared inline - -"Alternative syntax without the FIELDS addition -"Here, the CORRESPONDING FIELDS OF addition is used. Only the content of -"columns that have identically named components in the target data object -"is assigned. -SELECT SINGLE comp1, comp2, comp3   "Selected set of fields - FROM dbtab - WHERE ... - INTO CORRESPONDING FIELDS OF @struc. "Existing structure -``` -> **💡 Note**
->- Although its use is optional, a `WHERE` clause should be specified to further restrict the read result. ->- Regarding the addition `CORRESPONDING FIELDS OF` in the `INTO` - clause: As mentioned, only the content of columns for which there are identically named components in the target are assigned. However, if you want to read data into an existing data object and particular fields are specified in the `SELECT` list and if the addition is **not** specified, you might stumble on undesired results. The target data object must contain enough components and the content of the columns are assigned to the components of the target from left to right in the order specified after `SELECT`. The content of surplus components of the target is not changed. Plus, pay attention to [assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenselect_into_conversion.htm). Basic rule: Without `CORRESPONDING ...`, column names do not play a role but only the position. With `CORRESPONDING ...`, the position of the columns does not play a role but only the name. ->- Find more information regarding the addition `INTO` [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm). - -**Reading multiple rows into an internal table**. -``` abap -SELECT FROM dbtab - FIELDS *   "All fields - WHERE ... - INTO TABLE @itab. "itab has an appropriate row type - -"Alternative syntax without the FIELDS addition -SELECT comp1, comp2, comp3   "Selected set of fields - FROM dbtab - WHERE ... - INTO TABLE @DATA(lv_itab). "Internal table declared inline - -"Selected set of fields, existing variable -"See the note on CORRESPONDING FIELDS OF above -SELECT FROM dbtab - FIELDS comp1, comp2, comp3   "Selected set of fields - WHERE ... - INTO CORRESPONDING FIELDS OF TABLE @itab. -``` - -**`SELECT` loop: Sequentially reading multiple rows**. -- A `SELECT` loop can be opened if the assignment is made to a structure and the addition `SINGLE` is not used. -- If the row is found, the system field `sy-subrc` is set to `0`. -- The loop must be closed using `ENDSELECT`. -- To terminate the loop completely, you can use the statement [`EXIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapexit_loop.htm). -- Note: As covered further down, when using the addition `PACKAGE SIZE` and storing the result in a table, a loop is opened, too. - -``` abap -SELECT FROM dbtab - FIELDS * - WHERE ... - INTO @struc. - - IF sy-subrc = 0. -      ...  "For example, making changes on data and adding the row to an internal table. - - ENDIF. - -ENDSELECT. -``` -

⬆️ back to top

- -### Clause Variations and Additions in SELECT Statements - -`SELECT`/`FROM` clauses: - -**Checking the existence of a row in a database table** -``` abap -"Instead of @abap_true, you could also use 'X'. -SELECT SINGLE @abap_true - FROM dbtab - WHERE ... - INTO @DATA(exists). - -IF exists = abap_true. - ... -ENDIF. -``` - -**Removing rows that occur more than once in a multirow result set** using the `DISTINCT` addition. -- Cannot be used with the addition `SINGLE`. -- See more information here [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause.htm). -``` abap -SELECT DISTINCT comp1 - FROM dbtab - WHERE ... - INTO TABLE @itab. -``` - -**SELECT list variants** (some of them are already outlined above) +### SELECT List Variants The following specifications can also be combined: - `SELECT * ...`: As outlined above, the `*` character defines all columns to be read from a data source (in the order specified there). @@ -348,40 +247,185 @@ SELECT ds~col1, ds~col2, ds~col3 INTO ... ``` -

⬆️ back to top

-**Reading data from a database table in another client** ([classic ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassic_abap_glosry.htm) only). Note that there are several variants of the `USING ...` addition for switching the [implicit client handling (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_sql_client_handling.htm) from the current client to other clients. See more information [here (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselect_client.htm). -``` abap -"Some examples; not available in ABAP for Cloud Development +Most of the code snippets in this cheat sheet use database tables as the source in `SELECT` statements. Among others, you can also use internal tables or CDS view entities as data source +Note that an alias name must be specified for the internal table used as data source. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_itab.htm). -"Replaces the current client with the specified client -SELECT * - FROM dbtab USING CLIENT '000'             - WHERE ... - INTO TABLE @itab. - -"Selects data of any number of clients -SELECT * - FROM dbtab USING ALL CLIENTS - WHERE ... - INTO TABLE @itab. -``` - -**Reading data from an internal table as data source** using `SELECT`. Note that an alias name must be specified for the internal table used as data source. -Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_itab.htm). ``` abap SELECT * FROM @itab1 AS tab WHERE ... - INTO TABLE @DATA(itab2). + INTO .... + +SELECT * + FROM some_cds_view + WHERE ... + INTO .... ```

⬆️ back to top

-`INTO` **clause**: +### Retrieving Single and Multiple Rows -**Limiting the number of returned table rows** using the optional addition [`UP TO n ROWS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm). + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subject Details/Code Snippet
Retrieving a single row into a structure + +``` abap +"SINGLE addition +"Here, all fields of a single row a read. Specifying an +"asterisk * indicates that all fields are to be read. +"Alternatively, you can list all the fields separated by comma. +"Note that if the selection covers more than one row, e. g. in case +"of a non-unique WHERE clause, one of these rows is included in +"the result. +SELECT SINGLE FROM dbtab + FIELDS * + WHERE ... + INTO @struc. "Existing structure of dbtab's row type + +"Retrieving a selected set of fields of a single row +SELECT SINGLE FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE ... + INTO @DATA(struc2). "Structure declared inline + +"Alternative syntax without the FIELDS addition +"Here, the CORRESPONDING FIELDS OF addition is used. Only the content of +"columns that have identically named components in the target data object +"is assigned. +SELECT SINGLE comp1, comp2, comp3 "Selected set of fields + FROM dbtab + WHERE ... + INTO CORRESPONDING FIELDS OF @struc. "Existing structure +``` + +> **💡 Note**
+>- Although its use is optional, a `WHERE` clause should be specified to further restrict the read result. +>- Regarding the addition `CORRESPONDING FIELDS OF` in the `INTO` + clause: As mentioned, only the content of columns for which there are identically named components in the target are assigned. However, if you want to read data into an existing data object and particular fields are specified in the `SELECT` list and if the addition is **not** specified, you might stumble on undesired results. The target data object must contain enough components and the content of the columns are assigned to the components of the target from left to right in the order specified after `SELECT`. The content of surplus components of the target is not changed. Plus, pay attention to [assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenselect_into_conversion.htm). Basic rule: Without `CORRESPONDING ...`, column names do not play a role but only the position. With `CORRESPONDING ...`, the position of the columns does not play a role but only the name. +>- Find more information regarding the addition `INTO` [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm). + +
Retrieving multiple rows into an internal table + +``` abap +SELECT FROM dbtab + FIELDS * "All fields + WHERE ... + INTO TABLE @itab. "itab has an appropriate row type + +"Alternative syntax without the FIELDS addition +SELECT comp1, comp2, comp3 "Selected set of fields + FROM dbtab + WHERE ... + INTO TABLE @DATA(lv_itab). "Internal table declared inline + +"Selected set of fields, existing variable +"See the note on CORRESPONDING FIELDS OF above +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 "Selected set of fields + WHERE ... + INTO CORRESPONDING FIELDS OF TABLE @itab. +``` + +
SELECT loop: Sequentially retrieving multiple rows + +- A `SELECT` loop can be opened if the assignment is made to a structure and the addition `SINGLE` is not used. +- If the row is found, the system field `sy-subrc` is set to `0`. +- The loop must be closed using `ENDSELECT`. +- To terminate the loop completely, you can use the statement [`EXIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapexit_loop.htm). +- Note: As covered further down, when using the addition `PACKAGE SIZE` and storing the result in a table, a loop is opened, too. + +
+ +``` abap +SELECT FROM dbtab + FIELDS * + WHERE ... + INTO @struc. + + IF sy-subrc = 0. + ... "For example, making changes on data and adding the row to an internal table. + + ENDIF. + +ENDSELECT. +``` + +
Checking the existence of a row in a database table + + +``` abap +"Instead of @abap_true, you could also use 'X'. +SELECT SINGLE @abap_true + FROM dbtab + WHERE ... + INTO @DATA(exists). + +IF exists = abap_true. + ... +ENDIF. +``` + +
DISTINCT addition: Removing rows that occur more than once in a multirow result set + +- Cannot be used with the addition `SINGLE`. +- See more information here [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause.htm). + +
+ +``` abap +SELECT DISTINCT comp1 + FROM dbtab + WHERE ... + INTO TABLE @itab. +``` + +
+ +

⬆️ back to top

+ +### Miscellaneous Options Regarding the Result + +This section demonstrates different patterns of the ABAP SQL `SELECT` statement for handling query results. There is a wide range of options available, some of which have already been covered above. This section covers a selection of additions and syntax options. For complete details and syntax options, you can refer to the ABAP Keyword Documentation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -### More Clauses + + + + + + +
Subject Details/Code Snippet
UP TO n ROWS addition: Limiting the number of returned table rows + +[`UP TO n ROWS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm) + +
``` abap "A maximum of five rows are to be returned @@ -392,7 +436,17 @@ SELECT * FROM dbtab UP TO 5 ROWS. ``` -**Returning only the table rows after a row with a specified count from the result set** using the optional addition [`OFFSET n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm#!ABAP_ADDITION_2@2@). You can only use the addition, if an `ORDER BY` clause is specified. +
OFFSET n addition: Returning only the table rows after a row with a specified count from the result set + +- [`OFFSET n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm#!ABAP_ADDITION_2@2@) +- You can only use the addition, if an `ORDER BY` clause is specified. + +
``` abap "In the example, data of all flights are retrieved, except for the 2 flights @@ -405,7 +459,13 @@ SELECT * OFFSET 2. ``` -**Reading into individual elementary data objects**. +
Storing the result in individual elementary data objects + Apart from reading into structures and internal tables outlined above, you can also read into individual elementary data objects. Here, the individual elementary data objects as target objects are specified in a comma-separated list (e. g. as existing host variables or declared inline with `@DATA(...)`) and put between a pair of parentheses. Note: @@ -415,17 +475,27 @@ Note: - More information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm#!ABAP_ALTERNATIVE_1@1@). +
+ ``` abap SELECT FROM dbtab FIELDS comp1, comp2, comp3 WHERE ... INTO (@res1,@res2,@res3). - "INTO (@DATA(res1),@DATA(res2),@DATA(res3)). "Using inline declarations + "INTO (@DATA(res4),@DATA(res5),@DATA(res6)). "Using inline declarations ``` -**Appending the result set to an existing internal table**. +
APPENDING addition: Appending the result set to an existing internal table + The addition `INTO` initializes the target object. When using the addition `APPENDING`, you can retain existing lines in internal tables. `APPENDING` is also possible with the addition `CORRESPONDING FIELDS OF TABLE`. +
+ ``` abap SELECT * FROM dbtab WHERE ... @@ -436,7 +506,18 @@ SELECT * FROM dbtab APPENDING CORRESPONDING FIELDS OF TABLE @diff_itab. ``` -**Reading into packages of a specified number of rows** when reading into internal tables. The addition [`PACKAGE SIZE n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm#!ABAP_ONE_ADD@1@) can be specified after `INTO TABLE` and `APPENDING TABLE`. A `SELECT` loop ist opened. After `PACKAGE SIZE`, the number of rows is specified (which can be a host variable, host expression or a literal of type `i`) denoting the number of rows to be inserted in the target object per iteration. +
PACKAGE SIZE n addition: Storing the result in packages of a specified number of rows + + +The addition [`PACKAGE SIZE n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm#!ABAP_ONE_ADD@1@) can be specified after `INTO TABLE` and `APPENDING TABLE`. A `SELECT` loop ist opened. After `PACKAGE SIZE`, the number of rows is specified (which can be a host variable, host expression or a literal of type `i`) denoting the number of rows to be inserted in the target object per iteration. + +
+ ``` abap SELECT FROM dbtab FIELDS comp1, comp2, comp3 @@ -446,7 +527,17 @@ SELECT FROM dbtab ENDSELECT. ``` -**Specifying an [anonymous data object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm) as target object** using the addition [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_into_target.htm#!ABAP_ALTERNATIVE_3@3@). Only to be used after `INTO` and not `APPENDING`. +
NEW addition: Specifying an anonymous data object as target object + +- Specifying an [anonymous data object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm) as target object using the addition [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_into_target.htm#!ABAP_ALTERNATIVE_3@3@) +- Only to be used after `INTO` and not `APPENDING`. + +
``` abap "Here, the target object is an anonymous data object declared inline. @@ -456,643 +547,22 @@ SELECT FROM dbtab INTO TABLE NEW @DATA(dref). ``` -

⬆️ back to top

+
INDICATORS [NOT] NULL STRUCTURE addition: Specifying null indicators -[`GROUP BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapgroupby_clause.htm) -clause: Combining groups of table rows in the result set. You -might also use [SQL expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_expression_glosry.htm "Glossary Entry") -here. Multiple clause elements are separated by a comma. Find more -information on SQL expressions further down. +- The `INDICATORS ...` addition is used to specify indicators such as the [null indicator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_indicator_glosry.htm) and store information about which columns of the result set contain the null value and which do not. +- In the example, an appropriate target table is defined to also store information about which columns of the result set contain the null value and which do not. +- More syntax options are available for `INDICATORS ...`. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_indicators.htm). -Note that the `GROUP BY` clause requires all columns that are -directly specified in the `SELECT` list or specified there as an -argument of an SQL expression to be specified. An exception to this is -[aggregate -functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") -in [aggregate -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_expression_glosry.htm "Glossary Entry") -(except [grouping -functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengrouping_glosry.htm "Glossary Entry")) -as shown in the following example. - -In the example below, the database table rows that have the same content in column `comp1` are combined. The lowest and highest values in column `comp2` are determined for each of these groups and placed into the combined row. -``` abap -SELECT FROM dbtab - FIELDS comp1, MIN( comp2 ) AS min, MAX( comp2 ) AS max - WHERE ... - GROUP BY comp1 - INTO ... -``` - -[`HAVING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaphaving_clause.htm) -clause: Limiting the number of table rows in groups in the -result by setting conditions on these rows. The rows for which a -logical expression is true are inserted in the target variable. Note -that `HAVING` can only be used together with `GROUP BY`. -``` abap -SELECT FROM dbtab - FIELDS comp1, MIN( comp2 ) AS min, MAX( comp3 ) AS max - WHERE ... - GROUP BY comp1 - HAVING comp1 LIKE '%XYZ%' AND SUM( comp4 ) > 100 - INTO ... -``` - -[`ORDER BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaporderby_clause.htm) -clause: Sorting the result set by specified columns. - -The following example shows the ordering of the result set based on the -content of the primary key of the [data -source](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_source_glosry.htm "Glossary Entry"). -You can also order by any columns and by explicitly specifying the sort -order. There are more ordering options, for example, by using SQL -expressions. -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE ... - ORDER BY PRIMARY KEY - "comp2 ASCENDING - "comp2 DESCENDING - INTO ... -``` - -> **💡 Note**
->- Not specifying `ORDER BY` means that the order of entries in the result set is undefined. ->- If `ORDER BY` and `GROUP BY` clauses are used, all columns specified after `ORDER BY` must also be specified after `GROUP BY`. ->- If aggregate functions are specified after `SELECT`, all columns that are specified after `ORDER BY` and that do not have an alias name for an aggregate function must also be specified after `SELECT` and after the `GROUP BY` clause which is required in this case, too. - -[`WHERE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhere.htm) clause: Restricts the number of rows that are included in the result set using logical expressions. See further information on them in the following sections. -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE comp1 = 'abc' - AND comp2 < 123    - INTO ... -``` - -

⬆️ back to top

- -### Operands and Expressions in ABAP SQL Statements - -ABAP offers plenty of [SQL -operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_glosry.htm "Glossary Entry") -and -[expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_expression_glosry.htm "Glossary Entry") -that are possible in ABAP SQL statements, not only in the context of -`SELECT` statements and the `SELECT` lists which are -mainly used for the following demonstration examples. Questions about -when to use what, what is possible in which contexts and positions, is -beyond the scope of this cheat sheet. Check the details in the -respective topics in the ABAP Keyword Documentation. Find a general -overview of important operand positions in ABAP SQL -[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_positions_oview.htm). -Due to the rich variety of options, the cheat sheet covers a selection. - -#### SQL Operands - -- Are elementary operands in an ABAP SQL statement -- Can be database table or view columns, a - [literal](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_glosry.htm "Glossary Entry"), - [host - variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm "Glossary Entry") - (i. e. global or local data objects escaped using `@`: - `@dobj`) or [host - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_expression_glosry.htm "Glossary Entry") - (`@( ... )`) - - Regarding literals: They are not prefixed with the escape - character `@`. The literals can be - [typed](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentyped_literal_glosry.htm "Glossary Entry") - (using the type name and content within a pair of backquotes: - char\`abc\`) with [built-in ABAP Dictionary - types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_builtin_types.htm) - or untyped. Typed literals are preferable for the following - reasons: Using untyped literals means extra cost in terms of - performance since they must be converted by the compiler. Plus, - their use can result in errors at runtime whereas typed literals - guarantee type compatibility at once. For more information on [typed literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentyped_literal_glosry.htm), refer to the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_typed_literals.htm) and the [Typed Literals in ABAP SQL](/16_Data_Types_and_Objects.md#typed-literals-in-abap-sql) section of the *Data Types and Data Objects* cheat sheet. - - Regarding host expressions: Structures and internal tables are - possible as host expressions for statements modifying the - content of database tables as shown further down. -- See more information - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operands.htm). - -Example demonstrating possible operands: -``` abap -DATA upto TYPE i VALUE 3. - -SELECT FROM zdemo_abap_flsch - FIELDS -  "Specifies a column of a data source directly using its name - cityfrom, - -  "Column selector ~ can be used to prefix every specified column. -  "Here, it is optional. It is non-optional, e. g., if multiple data -  "sources in an ABAP SQL statement are edited and the column name -  "is not unique. - zdemo_abap_flsch~cityto, - - 'Lufthansa' AS name, "Untyped literal - - char`X` AS flag, "Typed literal - - @upto AS num, "Host variable - - @( cl_abap_context_info=>get_system_date( ) ) as date "Host expression - - WHERE carrid = 'LH'         "Untyped literal - AND countryfr = char`DE` "Typed literal - -  "Data object created inline and escaped with @ - INTO TABLE @DATA(it) - -  "The following clause shows all options having the same effect - UP TO 3 ROWS.         "Untyped numeric literal - "UP TO int4`3` ROWS.   "Typed numeric literal - "UP TO @upto ROWS.     "Host variable - "UP TO @( 10 - 7 ) ROWS. "Host expression -``` - -

⬆️ back to top

- -#### SQL Expressions - -- Expressions in an ABAP SQL statement that are passed to the database - system for evaluation. -- For example, SQL expressions can be specified as columns in the - `SELECT` list as demonstrated in most of the following examples. - Find information on more possible positions and general information - on SQL expressions - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm) - and the subtopics there. -- Built-in SQL functions can be specified as standalone functions in ABAP SQL or as operands of SQL expressions. The result is a value with the associated dictionary type. The arguments of the functions can cover one or more SQL expressions. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_builtin_functions.htm). - -##### Elementary Expressions - -- An elementary expression represents one of the four mentioned - operands above: A value from the database (the column name) or - values from an ABAP program passed to the database (literal, host - variable or host expression). -- As an example, see the `SELECT` list in the example above. -- See more information - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_elem.htm). - -##### Numeric Functions - -[Numeric functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith_func.htm) +
``` abap -SELECT SINGLE - carrname, - - "Division, result rounded to an integer - "Result: 2 - div( 4, 2 ) AS div, - - "Division, 3rd argument: result is rounded to the specified - "number of decimals - "Result: 0.33 - division( 1, 3, 2 ) AS division, - - "Result is rounded to first greater integer - "Result: 2 - ceil( decfloat34`1.333` ) AS ceil, - - "Result is the remainder of division - "Result: 1 - mod( 3, 2 ) AS mod, - - "Result: Largest integer value not greater than the specified value - "Result: 1 - floor( decfloat34`1.333` ) AS floor, - - "Returns the absolute number - "Result: 2 - abs( int4`-2` ) AS abs, - - "Result is rounded to the specified position after the decimal separator - "Result: 1.34 - round( decfloat34`1.337`, 2 ) AS round - - FROM zdemo_abap_carr - WHERE carrid = 'AA' - INTO @DATA(numeric_functions). -``` - -

⬆️ back to top

- -##### String Functions - -[String functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string_func.htm) - -``` abap -SELECT SINGLE - carrid,   "LH - carrname, "Lufthansa - url, "http://www.lufthansa.com - - "Concatenates strings, ignores trailing blanks - "Result: LHLufthansa - concat( carrid, carrname ) AS concat, - - "Concatenates strings, number denotes the blanks that are inserted - "Result: LH Lufthansa - concat_with_space( carrid, carrname, 1 ) AS concat_with_space, - - "First letter of a word -> uppercase, all other letters -> lowercase; - "note that a space and other special characters means a new word. - "Result: Http://Www.Lufthansa.Com - initcap( url ) AS initcap, - - "Position of the first occurrence of the substring specified - "Result: 6 - instr( carrname,'a' ) AS instr, - - "String of length n starting from the left of an expression; - "trailing blanks are ignored - "Result: Luft - left( carrname, 4 ) AS left, - - "Number of characters in an expression, trailing blanks are ignored - "Result: 24 - length( url ) AS length, - - "Checks if expression contains a PCRE expression; - "case-sensitive by default (case_sensitive parameter can be specified) - "Notes on the result: 1 = found, 0 = not found - "Result: 1 - like_regexpr( pcre  = '\..', "Period that is followed by any character -                value = url ) AS like_regex, - - "Returns position of a substring in an expression, - "3rd parameter = specifies offset (optional) - "4th parameter = determines the number of occurrences (optional) - "Result: 9 - locate( carrname, 'a', 0, 2 ) AS locate, - - "Searches a PCRE pattern, returns offset of match; - "many optional parameters: occurrence, case_sensitive, start, group - "Result: 21 - locate_regexpr( pcre = '\..', "Period followed by any character -                  value = url, -                  occurrence = 2 ) "2nd occurrence in the string - AS locate_regexpr, - - "Searches a PCRE pattern, returns offset of match + 1; - "many optional parameters: occurrence, case_sensitive, start, group - "Result: 2 - locate_regexpr_after( pcre = '.',  "Any character -                        value = url, -                        occurrence = 1 ) AS locate_regexpr_after, - - "Removes leading characters as specified in the 2nd argument, - "trailing blanks are removed - "Result: ufthansa - ltrim( carrname, 'L' ) AS ltrim, - - "Counts all occurrences of found PCRE patterns - "Result: 2 - occurrences_regexpr( pcre = '\..', "Period that is followed by any character -                       value = url ) AS occ_regex, - - "Replaces the 2nd argument with the 3rd in an expression - "Result: Lufth#ns# - replace( carrname, 'a', '#' ) AS replace, - - "Replaces a found PCRE expression; - "more parameters possible: occurrence, case_sensitive, start - "Result: http://www#ufthansa#om - replace_regexpr( pcre = '\..', "Period that is followed by any character -                   value = url, -                   with = '#' ) AS replace_regex, - - "Extracts a string with the length specified starting from the right - "Result: hansa - right( carrname, 5 ) AS right, - - "Expands string to length n (2nd argument); trailing blanks produced - "are replaced by the characters from the (3rd) argument - "Note that if n is less than the string, the expression is truncated - "on the right. - "Result: Lufthansa### - rpad( carrname, 12, '#' ) AS rpad, - - "All trailing characters that match the character of the 2nd argument - "are removed; trailing blanks are removed, too - "Result: Lufthans - rtrim( carrname, 'a' ) AS rtrim, - - "Returns a substring; 2nd argument = position from where to start; - "3rd argument: length of the extracted substring - "Result: fth - substring( carrname, 3, 3 ) AS substring, - - "Searches for a PCRE expression and returns the matched substring - "More parameters possible: occurrence, case_sensitive, start, group - "Result: .lu - substring_regexpr( pcre = '\...', "Period that is followed by any two characters -                     value = url ) AS substring_regexpr, - - "All lower case letters are transformed to upper case letters - "Result: LUFTHANSA - upper( carrname ) AS upper - - FROM zdemo_abap_carr - WHERE carrid = 'LH' - INTO @DATA(string_functions). -``` - -

⬆️ back to top

- -##### Special Functions - -[Special functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_special_functions.htm) - -``` abap -SELECT SINGLE - carrid, - -  "Conversion functions -  "When used: Special conversions that cannot be handled in a general -  "CAST expression - -  "Type conversion: string of fixed length (e.g. of type c) to variable -  "length string of type string - to_clob( carrid ) AS clob, - -  "Byte string -> character string - bintohex( raw`3599421128650F4EE00008000978B976` ) AS bintohex, - -  "Character string -> byte string - hextobin( char`3599421128650F4EE00008000978B976` ) AS hextobin, - -  "Byte field of type RAW to a byte string (BLOB) of type RAWSTRING - to_blob( raw`3599421128650F4EE00008000978B976` ) AS blob, - -  "Unit and currency conversion functions -  "More parameters are available. - -  "Converts miles to kilometers - unit_conversion( quantity = d34n`1`, -                   source_unit = unit`MI`, -                   target_unit = unit`KM` ) AS miles_to_km, - -  "Converts Euro to US dollars using today's rate - currency_conversion( -    amount = d34n`1`, -    source_currency = char`EUR`, -    target_currency = char`USD`, -    exchange_rate_date = @( cl_abap_context_info=>get_system_date( ) ) -                     ) AS eur_to_usd, - -  "Date and time functions - add_days( @( cl_abap_context_info=>get_system_date( ) ), 4 ) AS add_days, - add_months( @( cl_abap_context_info=>get_system_date( ) ), 2 ) AS add_months, - is_valid( @( cl_abap_context_info=>get_system_date( ) ) ) AS date_is_valid, - is_valid( @( cl_abap_context_info=>get_system_time( ) ) ) AS time_is_valid - -FROM zdemo_abap_carr -INTO @DATA(special_functions). -``` - -

⬆️ back to top

- -##### Aggregate Expressions - -[Aggregate expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm) - -- Consist of [aggregate - functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") - and aggregate the values of multiple rows of the result set of a - [query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenquery_glosry.htm "Glossary Entry") - into a single value -- See more information - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm). - -Example: -``` abap -"The example shows a selection of available functions -SELECT - carrid, - - "Average value of the content of a column in a row set - AVG( fltime ) AS fltime1, - - "AVG with data type specification for the result - AVG( fltime AS DEC( 14,4 ) ) AS fltime2, - - "Maximum value of the results in a row set - MAX( fltime ) AS max, - - "Minimum value - MIN( fltime ) AS min, - - "Sum of the results in a row set. - SUM( fltime ) AS sum, - - "Returns the number of rows in a row set. - "The following two have the same meaning. - COUNT( * ) AS count2, - COUNT(*) AS count3, - - "Chains the results in a row set. - "An optional separator can be specified - STRING_AGG( airpfrom, ', ' ) AS string_agg - - FROM zdemo_abap_flsch - WHERE carrid = 'LH' - GROUP BY carrid - INTO TABLE @DATA(agg_exp). -``` - -

⬆️ back to top

- -##### Arithmetic, Cast, String Expressions, and Case Distinctions - -- [Arithmetic - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith.htm) - to perform arithmetic calculations using the operators `+`, - `-`, `*`, `/`, -- [Cast - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast.htm) - to convert the value of operands to a dedicated dictionary type. - Note that there are special [conversion - rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast_rules.htm). -- [String - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string.htm) - using the operator `&&` to concatenate character strings. -- [Case - distinctions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_case.htm) - to carry out either a simple (comparison of the values of a - dedicated operand) or complex (searched case; evaluation of multiple - logical expressions) case distinction. - -The following example demonstrates the expressions mentioned above: -``` abap -SELECT SINGLE -  carrid, - -  "Arithmethic expressions -  "operators + - * -  "Note that / is not allowed in integer expressions as the one below -  ( 1 + 2 ) * 3 AS calc, - -  "/ used in an expression using type adjustment in ABAP SQL. -  "A cast expression converts the value of the operands to the -  "specified dictionary type. The result is a representation of the -  "source value in the specified type. - CAST( 1 AS D34N ) / CAST( 2 AS D34N ) AS ratio, - -  "String expression using && to concatenate two character strings; -  "the result of the concatenation must not be longer than -  "255 characters. -  carrid && carrname AS concat, - -  "Case distinction -  "Simple case distinction -  "The expression compares the values of an operand with other -  "operands. Result: The first operand after THEN for which the -  "comparison is true. If no matches are found, the result specified -  "after ELSE is selected. - CASE currcode - WHEN 'EUR' THEN 'A' - WHEN 'USD' THEN 'B' - ELSE 'C' - END AS case_simple, - -  "Complex case distinction -  "The expression evaluates logical expressions. Result: The first -  "operand after THEN for which the logical expression is true. If no -  "logical expressions are true, the result specified after ELSE is -  "selected. - CASE WHEN length( carrname ) <= 5 THEN 'small' - WHEN length( carrname ) BETWEEN 6 AND 10 THEN 'mid' - WHEN length( carrname ) BETWEEN 11 AND 15 THEN 'large' - ELSE 'huge' - END AS case_complex - -FROM zdemo_abap_carr -WHERE carrid = 'AA' -INTO @DATA(more_sql_expr). -``` - -

⬆️ back to top

- -##### Window Expressions - -How [window expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_expression_glosry.htm "Glossary Entry") work: - -- Define a subset of the result set (i. e. the - "[window](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_glosry.htm "Glossary Entry")") - of a database query that implements ABAP SQL -- Apply a [window - function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_function_glosry.htm "Glossary Entry") - - which evaluates the rows of the window and which can, for example, - be an [aggregate - function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") - like - [`AVG`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_agg_func&sap-language=EN&sap-client=000&version=X&anchor=!ABAP_VARIANT_1@1@&tree=X) - to determine the average value - to the result set -- I. e. a window is constructed by the rows of the result set for - which all the window functions have the same result; a value is then - determined for the rows of a window - -Setup of a statement with window expressions: - -- Window function, e. g. an aggregate function like `AVG`, - followed by `OVER( ... )` (the content in the parentheses - defines the "window") -- The content in the parentheses can contain the following additions: - - Optional `PARTITION BY`: Defines the windows using a - comma-separated list of [SQL - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm); - the window function is calculated for the rows of this window; - note that if the addition is not specified, the window comprises - all rows of the result set - - Optional `ORDER BY`: Introduces both an order (you can - use `ASCENDING` and `DESCENDING`) and a frame - (as outlined below) within the current window, which further - restricts the rows for which the window function is calculated - - A window frame, which stands for a subset of rows inside a - window, can optionally be defined if `ORDER BY` is - specified; there are 3 options to define the starting and ending - frame boundaries (see the example) - -See more information on window expressions and the syntax -[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_over.htm). - -Examples: -``` abap -"Example 1: A simple window is constructed in the OVER clause; -"window functions - here aggregate functions - are applied -SELECT carrid, currency, - SUM( paymentsum ) OVER( PARTITION BY carrid ) AS sum, - AVG( price AS DEC( 14,2 ) ) OVER( PARTITION BY carrid ) AS avg, - MAX( price ) OVER( PARTITION BY carrid ) AS max - FROM zdemo_abap_fli - ORDER BY carrid - INTO TABLE @DATA(win). - -"Example 2: -SELECT carrid, currency, fldate, -  "Sorts the rows by some columns and counts the number of rows from -  "the first row of the window to the current row. - COUNT( * ) OVER( ORDER BY currency, fldate - ROWS BETWEEN - "UNBOUNDED PRECEDING: frame starts at the first row of the window - UNBOUNDED PRECEDING -                   "CURRENT ROW: determines starting or ending at the current row; here, it ends - AND CURRENT ROW ) AS count1, - -  "If no window frame is used, the default window frame is -  "BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, -  "i. e. the result of count1 equals the result of count2. - COUNT( * ) OVER( ORDER BY currency, fldate ) AS count2, - -  "Sorts the rows by some columns and counts the number of rows from -  "the current row to the last row of the window. -  "The result is reverse numbering. - COUNT( * ) OVER( ORDER BY currency, fldate - ROWS BETWEEN CURRENT ROW -                   UNBOUND FOLLOWING: -                   "Determines the ending frame boundary, this addition specifies the last row of the window - AND UNBOUNDED FOLLOWING ) AS count_reverse, - -  "Sorts the rows by some columns and calculates the rolling averages -  "of a subset of rows from column price. The subset consists of the -  "current row plus one preceding and one following row. Another use -  "case as below example that uses prices would be that, for example, -  "you can calculate the 3-day-average temperature for every day from -  "a list of temperature data. - AVG( price AS DEC( 14,2 ) ) OVER( ORDER BY currency, fldate - ROWS BETWEEN -       "n PRECEDING: for both start and end of frame; frame to start/end n rows above the current row - 1 PRECEDING -       "n FOLLOWING: for both start and end of frame; frame to start/end n rows beneath the current row - AND 1 FOLLOWING ) AS avg - - FROM zdemo_abap_fli - INTO TABLE @DATA(result). -``` - -

⬆️ back to top

- -##### coalesce Function - -Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_coalesce.htm). - - -```abap -"The null value is a special value that is returned by a database. It indicates an -"undefined value or result. Note that, in ABAP, there are no special null values. Do -"not confuse the null value with a type-dependent initial value. When using SELECT -"statements to read data, null values can be produced by, for example, outer joins. -"When the null values are passed to a data object, they are transformed to the -"type-dependent initial values. For more information, refer to the ABAP Keyword Documentation. "The following example uses a left outer join to intentionally create null values. For -"this purpose, two demo database tables of the ABAP cheat sheet repository are cleared and +"this purpose, two demo database tables of the cheat sheet repository are cleared and "populated with specific values to visualize null values. DELETE FROM zdemo_abap_tab1. DELETE FROM zdemo_abap_tab2. @@ -1107,33 +577,396 @@ MODIFY zdemo_abap_tab2 FROM TABLE @( VALUE #( ( key_field = 1 char1 = 'a' ) "char1 is a shared column of the two database tables, and which is used in "the ON condition of the join. Since there is no entry in char1 for 'key_field = 4', "the joined values are null in that case. -"The coalesce function is used to replace null values produced by an outer join with -"a different value. -SELECT tab2~key_field, - coalesce( tab1~char1, '-' ) AS coalesced1, - coalesce( tab1~char2, '#' ) AS coalesced2, - "A coalesce function is a short form of a complex - "case distinction such as the following: - CASE WHEN tab1~char1 IS NOT NULL THEN tab1~char1 - ELSE '?' - END as coalesced3 +"The example visualizes the null values. The INDICATORS addition is used to specify +"indicators such as the null indicator. In the example, an appropriate target table +"is defined to also store information about which columns of the result set contain +"the null value and which do not. +TYPES: BEGIN OF st4null, + BEGIN OF s2, + key_field TYPE zdemo_abap_tab2-key_field, + char2 TYPE zdemo_abap_tab1-char2, + END OF s2, + BEGIN OF nulls, + key_field TYPE c LENGTH 1, + char2 TYPE c LENGTH 1, + END OF nulls, + END OF st4null. +DATA joined_tab_w_null_ind TYPE TABLE OF st4null WITH EMPTY KEY. - FROM zdemo_abap_tab2 AS tab2 - LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 - INTO TABLE @DATA(join_w_null). +SELECT tab2~key_field, tab1~char2 + FROM zdemo_abap_tab2 AS tab2 + LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 + INTO TABLE @joined_tab_w_null_ind INDICATORS NULL STRUCTURE nulls. -*Example table content -*KEY_FIELD COALESCED1 COALESCED2 COALESCED3 -*1 a y a -*2 a y a -*3 b z b -*4 - # ? +*Internal table content: +*S2 NULLS +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*1 y +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*2 y +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*3 z +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*4 X +``` + +
+ +

⬆️ back to top

+ +### Additional Clauses + + + + + + + + + + + + + + + + + + + + + + + +
Clause Details/Code Snippet
GROUP BY + +[`GROUP BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapgroupby_clause.htm) +clause: Combining groups of table rows in the result set. You +can also use [SQL expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_expression_glosry.htm "Glossary Entry") +here. Multiple clause elements are separated by a comma. Find more information and syntax options in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapgroupby_clause.htm). + +Note that the `GROUP BY` clause requires all columns that are +directly specified in the `SELECT` list or specified there as an +argument of an SQL expression to be specified. An exception to this is +[aggregate +functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") +in [aggregate +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_expression_glosry.htm "Glossary Entry") +(except [grouping +functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengrouping_glosry.htm "Glossary Entry")) +as shown in the following example. + +In the example below, the database table rows that have the same content in column `comp1` are combined. The lowest and highest values in column `comp2` are determined for each of these groups and placed into the combined row. + +
+ +``` abap +SELECT FROM dbtab + FIELDS comp1, MIN( comp2 ) AS min, MAX( comp2 ) AS max + WHERE ... + GROUP BY comp1 + INTO ... +``` + +
HAVING + + +[`HAVING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaphaving_clause.htm) +clause: Limiting the number of table rows in groups in the +result by setting conditions on these rows. The rows for which a +logical expression is true are inserted in the target variable. Note +that `HAVING` can only be used together with `GROUP BY`. + +
+ +``` abap +SELECT FROM dbtab + FIELDS comp1, MIN( comp2 ) AS min, MAX( comp3 ) AS max + WHERE ... + GROUP BY comp1 + HAVING comp1 LIKE '%XYZ%' AND SUM( comp4 ) > 100 + INTO ... +``` + +
ORDER BY + +[`ORDER BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaporderby_clause.htm) +clause: Sorting the result set by specified columns. + +The following example shows the ordering of the result set based on the +content of the primary key of the [data source](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_source_glosry.htm "Glossary Entry"). +You can also order by any columns and by explicitly specifying the sort order. There are more ordering options, for example, by using SQL expressions. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaporderby_clause.htm). + +> **💡 Note**
+>- Not specifying `ORDER BY` means that the order of entries in the result set is undefined. +>- If `ORDER BY` and `GROUP BY` clauses are used, all columns specified after `ORDER BY` must also be specified after `GROUP BY`. +>- If aggregate functions are specified after `SELECT`, all columns that are specified after `ORDER BY` and that do not have an alias name for an aggregate function must also be specified after `SELECT` and after the `GROUP BY` clause which is required in this case, too. + + +
+ +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE ... + ORDER BY PRIMARY KEY + "comp2 ASCENDING + "comp2 DESCENDING + INTO ... +``` +
WHERE + +[`WHERE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhere.htm) clause: Restricts the number of rows that are included in the result set using logical expressions. See further information on them in the following sections. + +
+ +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE comp1 = 'abc' + AND comp2 < 123 + INTO ... +``` + +
+ +

⬆️ back to top

+ +### Selecting Data by Evaluating the Content of Other Tables + +[`FOR ALL ENTRIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm) +addition: +- Components of an internal table can be used in the `WHERE` clause in logical expressions for comparisons with a column of the data source. +- The logical expression is evaluated for each individual row of the internal table. +- The result set of the `SELECT` statement is the union set of the result sets produced by the individual evaluations. Rows that occur more than once are removed from the result set automatically. The entire content of a row is respected. +- If `FOR ALL ENTRIES` is specified, there must be at least one comparison with a column of the internal table. +- For more information, especially restricitions and things to pay attention to (e. g. making sure that the internal table is not initial), see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm). + +``` abap +"Checking that table is not initial +IF ( 0 < lines( itab2 ) ). + + SELECT comp1, comp2, comp3 + FROM dbtab + FOR ALL ENTRIES IN @itab2 "Host variable before internal table + WHERE comp1 = @itab2-comp1 ... "Relational expression on the right side of a comparison + INTO TABLE @itab1 + +ENDIF. +``` + +**Checking the result set of a subquery** with the addition [`EXISTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_exists.htm) + +See possible clauses and additions of a [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm) in a condition in ABAP SQL [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_subquery.htm). + +The following code snippet includes a parenthesized subquery following `EXISTS`. Data is only selected from `dbtab1` if the relational expression (`WHERE EXISTS ...`) is true, i. e. if the result set of the subquery contains at least one row. Note the components of the table that are referenced using a tilde. + +``` abap +SELECT comp1, comp2, comp3 + FROM dbtab1 AS tab1 + WHERE EXISTS + ( SELECT comp1 FROM dbtab2 + WHERE comp1 = tab1~comp1 AND comp2 = tab1~comp2 ) + INTO ... +``` + +

⬆️ back to top

+ +### Combining Data of Multiple Tables + +**Using an [inner join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninner_join_glosry.htm)**: +- Columns of two or more data sources in a result set can be joined. +- Result set: + - Columns of the rows in the result set of the left side with the columns of the rows in the result set of the right side are joined into a single result set. + - Contains all combinations of rows for whose columns the join condition is true. +- If there are identical column names in multiple data sources, use the [column +selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_comp_selector_glosry.htm "Glossary Entry") +`~`. +``` abap +SELECT a~comp1, a~comp2, b~comp3, c~comp4 + FROM dbtab1 AS a + INNER JOIN dbtab2 AS b ON a~comp1 = b~comp1 AND a~comp2 = b~comp2 + INNER JOIN dbtab3 AS c ON a~comp1 = c~comp1 + WHERE ... + INTO ... +``` + +**Using an [outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenouter_join_glosry.htm)**: +- Realized by either a [left outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenleft_outer_join_glosry.htm) or +a [right outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenright_outer_join_glosry.htm). +- Result set: + - Same result set as the inner join. + - Difference: For each selected row on the left side as `LEFT OUTER JOIN` or on the right side as `RIGHT OUTER JOIN`, at least one row is created in the result set even if no rows on the other side meet the condition. The columns on the other side that do not meet the condition are filled with [null values](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm). + +``` abap +"Example for a left outer join +SELECT a~comp1, a~comp2, b~comp3, + FROM dbtab1 AS a + LEFT OUTER JOIN dbtab2 AS b ON a~comp1 = b~comp1 + WHERE ... + INTO ... +``` +> **💡 Note**
+> There are more join variants and syntax options available. See the ABAP Keyword Documentation on [joins](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_join.htm) +for more information. + +**Merging the result sets of multiple queries into a single result set** using the [set operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_set_operators_glosry.htm) [`UNION`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapunion.htm#!ABAP_VARIANT_1@1@). In this case, the rows of the result set of the query after `UNION` are inserted into the result set of the query in front of `UNION`. + +``` abap +SELECT FROM dbtab1 + FIELDS ... + WHERE ... +UNION +SELECT FROM dbtab2 + FIELDS ... + WHERE ... + INTO ... +``` + +**Returning distinct rows of a result set (1)** of a query specified before the `INTERSECT` addition that are also available in the result set of the query after the `INTERSECT` addition. + + +``` abap +"If you have imported the cheat sheet repository and already run an example class to fill +"the demo tables, you can check the contents of the result sets. +SELECT zdemo_abap_flsch~carrid, zdemo_abap_carr~carrname + FROM zdemo_abap_flsch + INNER JOIN zdemo_abap_carr ON zdemo_abap_carr~carrid = zdemo_abap_flsch~carrid + ORDER BY zdemo_abap_flsch~carrid + INTO TABLE @DATA(itab_no_intersect). + +"Using INTERSECT; the result set contains distinct rows +SELECT zdemo_abap_flsch~carrid, zdemo_abap_carr~carrname + FROM zdemo_abap_flsch + INNER JOIN zdemo_abap_carr ON zdemo_abap_carr~carrid = zdemo_abap_flsch~carrid +INTERSECT +SELECT carrid, carrname + FROM zdemo_abap_carr + ORDER BY carrid + INTO TABLE @DATA(itab_w_intersect). +``` + +**Returning distinct rows of a result set (2)** of a query specified before the `EXCEPT` addition that are not available in the result set of the query after the `EXCEPT` addition. + +```abap +"If you have imported the cheat sheet repository and already run an example class to fill +"the demo tables, you can check the contents of the result sets. + +"Selecting all carrier IDs from a database table that do not exist in an +"internal table +TYPES: ty_demo_tab TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY. +DATA(itab) = VALUE ty_demo_tab( ( carrid = 'LH' ) ( carrid = 'LH' ) ( carrid = 'LH' ) + ( carrid = 'AA' ) ( carrid = 'AA' ) ). + + +"Selecting all carrier IDs for comparison +SELECT carrid + FROM zdemo_abap_carr + INTO TABLE @DATA(all_carrids). + +"Using EXCEPT; the result set excludes those carrier IDs present in the +"internal table +SELECT carrid + FROM zdemo_abap_carr + EXCEPT + SELECT it~carrid + FROM @itab AS it + INNER JOIN zdemo_abap_carr ON zdemo_abap_carr~carrid = it~carrid + ORDER BY carrid ASCENDING + INTO TABLE @DATA(itab_w_except). +``` + +> **💡 Note**
+> There a more syntax options and contexts for `UNION`, `INTERSECT`, and `EXCEPT`. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapunion.htm). + +

⬆️ back to top

+ +### Common Table Expressions (CTE) + +When to use [Common Table Expressions (CTE)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencommon_table_expression_glosry.htm): + +- Whenever you need intermediate results in a `SELECT` + statement and especially if you need them more than once. +- You get the option of selecting directly from a subquery (`SELECT FROM subquery`), which is not possible in ABAP SQL. + +How they work: + +- The ABAP SQL keyword + [`WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) + introduces the definition of CTEs. +- Each CTE creates a tabular result set in a + [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). +- The result set of such a CTE can then be used in subsequent queries + as data source; CTEs can be considered as temporary views, which + only exist for the duration of the database access. +- The CTEs (at least one) are then used in a final [main + query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmainquery_glosry.htm "Glossary Entry"), i. + e. a `SELECT` statement accesses the result of the + expressions. + +Setup of a statement with CTE: + +- Introductory keyword `WITH` +- A comma-separated list with at least one definition of a CTE + - Each CTE has a unique name with an initial `+` character + - An optional list of column names, which should be used in the + result set, within parentheses + - `AS` followed by a subquery with `SELECT` which + creates the tabular result set of the CTE +- A closing main query with `SELECT` in which the previous + CTEs are to be used as data source +- If a `SELECT` loop is opened and data is written into a work + area in the closing main query, the loop must be closed with + `ENDWITH.` (which fulfills the same task as + `ENDSELECT.`). + +> **💡 Note**
+>- Each CTE must be used at least once, either in another CTE or in the + main query. The main query must access at least one CTE. +>- The result set of a CTE never has a [client + column](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclient_column_glosry.htm "Glossary Entry"). +>- See more information in [this topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) +and further options and additions when using CTEs in the subtopics. + +Example: The result sets of both common table expressions +`+connections` and `+sum_seats` are merged in the +subquery of the CTE `+result` in a join expression. An explicit +name list assigns names to the resulting columns. These names are used +in the main query to sort the results. For each flight connection of the +selected airline, the total number of occupied seats is stored in the +internal table. +``` abap +WITH ++connections AS ( + SELECT zdemo_abap_flsch~carrid, carrname, connid, cityfrom, cityto + FROM zdemo_abap_flsch + INNER JOIN zdemo_abap_carr + ON zdemo_abap_carr~carrid = zdemo_abap_flsch~carrid + WHERE zdemo_abap_flsch~carrid BETWEEN 'AA' AND 'JL' ), ++sum_seats AS ( + SELECT carrid, connid, SUM( seatsocc ) AS sum_seats + FROM zdemo_abap_fli + WHERE carrid BETWEEN 'AA' AND 'JL' + GROUP BY carrid, connid ), ++result( name, connection, departure, arrival, occupied ) AS ( + SELECT carrname, c~connid, cityfrom, cityto, sum_seats + FROM +connections AS c + INNER JOIN +sum_seats AS s + ON c~carrid = s~carrid AND c~connid = s~connid ) +SELECT * + FROM +result + ORDER BY name, connection + INTO TABLE @DATA(result). ```

⬆️ back to top

-### SQL Conditions +## SQL Conditions You can formulate conditions in ABAP SQL statements, i. e. [logical expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogical_expression_glosry.htm "Glossary Entry"), @@ -1165,7 +998,7 @@ topic. >You can combine multiple logical expressions into one logical expression using `AND` or `OR`. To further detail out the desired condition, expressions within parentheses are -possible. +possible. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_andornot.htm). Examples: @@ -1408,181 +1241,694 @@ SELECT tab2~key_field, tab1~char2

⬆️ back to top

-### Selecting Data by Evaluating the Content of Other Tables +## SQL Operands -[`FOR ALL ENTRIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm) -addition: -- Components of an internal table can be used in the `WHERE` clause in logical expressions for comparisons with a column of the data source. -- The logical expression is evaluated for each individual row of the internal table. -- The result set of the `SELECT` statement is the union set of the result sets produced by the individual evaluations. Rows that occur more than once are removed from the result set automatically. The entire content of a row is respected. -- If `FOR ALL ENTRIES` is specified, there must be at least one comparison with a column of the internal table. -- For more information, especially restricitions and things to pay attention to (e. g. making sure that the internal table is not initial), see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm). +- [SQL +operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_glosry.htm "Glossary Entry") are elementary operands in ABAP SQL statements +- Can be database table or view columns, a + [literal](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_glosry.htm "Glossary Entry"), + [host + variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm "Glossary Entry") + (i. e. global or local data objects escaped using `@`: + `@dobj`) or [host + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_expression_glosry.htm "Glossary Entry") + (`@( ... )`) + - Regarding literals: They are not prefixed with the escape + character `@`. The literals can be + [typed](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentyped_literal_glosry.htm "Glossary Entry") + (using the type name and content within a pair of backquotes: + char\`abc\`) with [built-in ABAP Dictionary + types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_builtin_types.htm) + or untyped. Typed literals are preferable for the following + reasons: Using untyped literals means extra cost in terms of + performance since they must be converted by the compiler. Plus, + their use can result in errors at runtime whereas typed literals + guarantee type compatibility at once. For more information on [typed literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentyped_literal_glosry.htm), refer to the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_typed_literals.htm) and the [Typed Literals in ABAP SQL](/16_Data_Types_and_Objects.md#typed-literals-in-abap-sql) section of the *Data Types and Data Objects* cheat sheet. + - Regarding host expressions: Structures and internal tables are + possible as host expressions for statements modifying the + content of database tables as shown further down. +- Find more information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operands.htm). + +> **💡 Note**
+> Questions about when to use what, what is possible in which contexts and positions, is beyond the scope of this cheat sheet. Check the details in the +respective topics in the ABAP Keyword Documentation. Find a general overview of important operand positions in ABAP SQL [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_positions_oview.htm). Due to the rich variety of options, the cheat sheet covers a selection. + + +Example demonstrating possible operands: ``` abap -"Checking that table is not initial -IF ( 0 < lines( itab2 ) ). +DATA number TYPE i VALUE 3. - SELECT comp1, comp2, comp3 - FROM dbtab - FOR ALL ENTRIES IN @itab2   "Host variable before internal table - WHERE comp1 = @itab2-comp1 ... "Relational expression on the right side of a comparison - INTO TABLE @itab1 +SELECT FROM zdemo_abap_flsch + FIELDS + "Specifies a column of a data source directly using its name + cityfrom, -ENDIF. -``` + "Column selector ~ can be used to prefix every specified column. + "Here, it is optional. It is non-optional, e. g., if multiple data + "sources in an ABAP SQL statement are edited and the column name + "is not unique. + zdemo_abap_flsch~cityto, -**Checking the result set of a subquery** with the addition [`EXISTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_exists.htm) + 'Lufthansa' AS name, "Untyped literal -See possible clauses and additions of a [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm) in a condition in ABAP SQL [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_subquery.htm). + char`X` AS flag, "Typed literal -The following code snippet includes a parenthesized subquery following `EXISTS`. Data is only selected from `dbtab1` if the relational expression (`WHERE EXISTS ...`) is true, i. e. if the result set of the subquery contains at least one row. Note the components of the table that are referenced using a tilde. + @number AS num, "Host variable -``` abap -SELECT comp1, comp2, comp3 - FROM dbtab1 AS tab1 - WHERE EXISTS - ( SELECT comp1 FROM dbtab2 - WHERE comp1 = tab1~comp1 AND comp2 = tab1~comp2 ) - INTO ... + @( cl_abap_context_info=>get_system_date( ) ) as date "Host expression + + WHERE carrid = 'LH' "Untyped literal + AND countryfr = char`DE` "Typed literal + + "Data object created inline and escaped with @ + INTO TABLE @DATA(it) + + "The following clause shows all options having the same effect + UP TO 3 ROWS. "Untyped numeric literal + "UP TO int4`3` ROWS. "Typed numeric literal + "UP TO @number ROWS. "Host variable + "UP TO @( 10 - 7 ) ROWS. "Host expression ```

⬆️ back to top

-### Combining Data of Multiple Database Tables -**Using an [inner join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninner_join_glosry.htm)**: -- Columns of two or more data sources in a result set can be joined. -- Result set: - - Columns of the rows in the result set of the left side with the columns of the rows in the result set of the right side are joined into a single result set. - - Contains all combinations of rows for whose columns the join condition is true. -- If there are identical column names in multiple data sources, use the [column -selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_comp_selector_glosry.htm "Glossary Entry") -`~`. -``` abap -SELECT a~comp1, a~comp2, b~comp3, c~comp4 - FROM dbtab1 AS a - INNER JOIN dbtab2 AS b ON a~comp1 = b~comp1 AND a~comp2 = b~comp2 - INNER JOIN dbtab3 AS c ON a~comp1 = c~comp1 - WHERE ... - INTO ... -``` +## SQL Expressions -**Using an [outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenouter_join_glosry.htm)**: -- Realized by either a [left outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenleft_outer_join_glosry.htm) or -a [right outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenright_outer_join_glosry.htm). -- Result set: - - Same result set as the inner join. - - Difference: For each selected row on the left side as `LEFT OUTER JOIN` or on the right side as `RIGHT OUTER JOIN`, at least one row is created in the result set even if no rows on the other side meet the condition. The columns on the other side that do not meet the condition are filled with [null values](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm). +- SQL expressions can be specified in various positions of ABAP SQL statements. +- They that passed to the database system for evaluation. +- For example, SQL expressions can be specified as columns in the + `SELECT` list as demonstrated in most of the following examples. +- Find information on more possible positions and general information + on SQL expressions + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm) + and the subtopics there. -``` abap -"Example for a left outer join -SELECT a~comp1, a~comp2, b~comp3, - FROM dbtab1 AS a - LEFT OUTER JOIN dbtab2 AS b ON a~comp1 = b~comp1 - WHERE ... - INTO ... -``` > **💡 Note**
-> There are more join variants available. See the ABAP -Keyword Documentation on -[joins](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_join.htm) -for more information. +> You can [enclose SQL expressions in parentheses](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_exp_parentheses.htm). +> ```abap +> SELECT SINGLE +> carrid, +> +> "SQL expressions enclosed in parenthesis in the context +> "of arithmetic expressions impacting the prioriry of +> "calculations +> ( 1 + 2 ) * ( 3 + 4 ) * ( 5 + 6 ) AS calc_w_par, "231 +> 1 + 2 * 3 + 4 * 5 + 6 AS calc_no_par "33 +> +> FROM zdemo_abap_fli +> WHERE carrid = 'AA' +> INTO @DATA(using_parentheses). +> ``` -**Merging the result sets of multiple queries into a single result set** using the [set operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_set_operators_glosry.htm) [`UNION`](http://ldcialx.wdf.sap.corp:50018/sap/public/bc/abap/docu?object=abapunion&sap-language=EN&sap-client=000&version=A&tree=X). In this case, the rows of the result set of the query after `UNION` are inserted into the result set of the query in front of `UNION`. +

⬆️ back to top

+ +### Elementary SQL Expressions + +- An elementary expression represents one of the four mentioned + operands above: A value from the data source (i.e. the column name), values from an ABAP program passed to the database (literal, host + variable or host expression). +- As an example, see the `SELECT` list in the example above. +- See more information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_elem.htm). + +

⬆️ back to top

+ +### Arithmetic Expressions + +[Arithmetic expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith.htm) perform arithmetic calculations using the operators `+`, `-`, `*`, `/`. ``` abap -SELECT FROM dbtab1 - FIELDS ... - WHERE ... -UNION - SELECT FROM dbtab2 - FIELDS ... - WHERE ... - INTO ... +SELECT SINGLE + carrid, + + "Arithmethic expressions + "operators + - * + "Note that / is not allowed in integer expressions as the one below + ( 1 + 2 ) * 3 AS calc, + + "/ used in an expression using type adjustment in ABAP SQL. + "A cast expression converts the value of the operands to the + "specified dictionary type. The result is a representation of the + "source value in the specified type. + CAST( 1 AS D34N ) / CAST( 2 AS D34N ) AS ratio + +FROM zdemo_abap_carr +WHERE carrid = 'AA' +INTO @DATA(arithmetic_sql_expr). ```

⬆️ back to top

-#### Common Table Expressions (CTE) +### Cast Expressions -When to use [Common Table Expressions (CTE)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencommon_table_expression_glosry.htm): +- [Cast expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast.htm) are used to convert the value of operands to a dedicated dictionary type. +- Note that there are special [conversion rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast_rules.htm). +- See the possible types in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast.htm). -- Whenever you need intermediate results in a `SELECT` - statement and especially if you need them more than once. -- You get the option of selecting directly from a subquery (`SELECT FROM subquery`), which is not possible in ABAP SQL. +```abap +SELECT SINGLE + carrid, -How it works: + "A cast expression converts the value of the operands to the + "specified dictionary type. The result is a representation of the + "source value in the specified type. + CAST( 1 AS D34N ) / CAST( 2 AS D34N ) AS ratio, + CAST( connid AS INT4 ) AS connidnum, + CAST( @( cl_abap_context_info=>get_system_date( ) ) AS CHAR ) AS dat -- The ABAP SQL keyword - [`WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) - introduces the definition of CTEs. -- Each CTE creates a tabular result set in a - [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). -- The result set of such a CTE can then be used in subsequent queries - as data source; CTEs can be considered as temporary views, which - only exist for the duration of the database access. -- The CTEs (at least one) are then used in a final [main - query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmainquery_glosry.htm "Glossary Entry"), i. - e. a `SELECT` statement accesses the result of the - expressions. +FROM zdemo_abap_fli +WHERE carrid = 'AA' +INTO @DATA(cast_expr). +``` -Setup of a statement with CTE: +

⬆️ back to top

-- Introductory keyword `WITH` -- A comma-separated list with at least one definition of a CTE - - Each CTE has a unique name with an initial `+` character - - An optional list of column names, which should be used in the - result set, within parentheses - - `AS` followed by a subquery with `SELECT` which - creates the tabular result set of the CTE -- A closing main query with `SELECT` in which the previous - CTEs are to be used as data source -- If a `SELECT` loop is opened and data is written into a work - area in the closing main query, the loop must be closed with - `ENDWITH.` (which fulfills the same task as - `ENDSELECT.`). +### String Expressions -> **💡 Note**
->- Each CTE must be used at least once, either in another CTE or in the - main query. The main query must access at least one CTE. ->- The result set of a CTE never has a [client - column](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclient_column_glosry.htm "Glossary Entry"). ->- See more information in [this topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) -and further options and additions when using CTEs in the subtopics. +[String expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string.htm) use the operator `&&` to concatenate character strings. -Example: The result sets of both common table expressions -`+connections` and `+sum_seats` are merged in the -subquery of the CTE `+result` in a join expression. An explicit -name list assigns names to the resulting columns. These names are used -in the main query to sort the results. For each flight connection of the -selected airline, the total number of occupied seats is stored in the -internal table. +```abap +SELECT SINGLE + carrid, + + "String expression using && to concatenate two character strings; + "the result of the concatenation must not be longer than + "255 characters. + carrid && char`_` && carrname AS concat + +FROM zdemo_abap_carr +WHERE carrid = 'AA' +INTO @DATA(string_expr). +``` + +

⬆️ back to top

+ +### Case Expressions + +- [Case expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_case.htm) carry out either a simple (comparison of the values of a dedicated operand) or complex (searched case; evaluation of multiple logical expressions) case distinction. +- Not specifying `ELSE` means that the result is the [null value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm). The null value can be specified explicitly by the null expression `NULL`. + +```abap +SELECT SINGLE + carrid, + + "Simple case distinction + "The expression compares the values of an operand with other + "operands. Result: The first operand after THEN for which the + "comparison is true. If no matches are found, the result specified + "after ELSE is selected. + CASE currcode + WHEN 'EUR' THEN 'A' + WHEN 'USD' THEN 'B' + ELSE 'C' + END AS case_simple, + + "Complex case distinction + "The expression evaluates logical expressions. Result: The first + "operand after THEN for which the logical expression is true. If no + "logical expressions are true, the result specified after ELSE is + "selected. + CASE WHEN length( carrname ) <= 5 THEN 'small' + WHEN length( carrname ) BETWEEN 6 AND 10 THEN 'mid' + WHEN length( carrname ) BETWEEN 11 AND 15 THEN 'large' + ELSE 'huge' + END AS case_complex + +FROM zdemo_abap_carr +WHERE carrid = 'AA' +INTO @DATA(cast_expr). +``` + +

⬆️ back to top

+ +### Aggregate Expressions + +- [Aggregate expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm) consist of [aggregate functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") + and aggregate the values of multiple rows of the result set of a + [query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenquery_glosry.htm "Glossary Entry") + into a single value +- The example shows a selection. Find more information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm). + +Example: ``` abap -WITH -+connections AS ( - SELECT zdemo_abap_flsch~carrid, carrname, connid, cityfrom, cityto - FROM zdemo_abap_flsch - INNER JOIN zdemo_abap_carr - ON zdemo_abap_carr~carrid = zdemo_abap_flsch~carrid - WHERE zdemo_abap_flsch~carrid BETWEEN 'AA' AND 'JL' ), -+sum_seats AS ( - SELECT carrid, connid, SUM( seatsocc ) AS sum_seats - FROM zdemo_abap_fli - WHERE carrid BETWEEN 'AA' AND 'JL' - GROUP BY carrid, connid ), -+result( name, connection, departure, arrival, occupied ) AS ( - SELECT carrname, c~connid, cityfrom, cityto, sum_seats - FROM +connections AS c - INNER JOIN +sum_seats AS s - ON c~carrid = s~carrid AND c~connid = s~connid ) -SELECT * - FROM +result - ORDER BY name, connection +"The example shows a selection of available functions +SELECT + carrid, + + "Average value of the content of a column in a row set + AVG( fltime ) AS fltime1, + + "AVG with data type specification for the result + AVG( fltime AS DEC( 14,4 ) ) AS fltime2, + + "Maximum value of the results in a row set + MAX( fltime ) AS max, + + "Minimum value + MIN( fltime ) AS min, + + "Sum of the results in a row set. + SUM( fltime ) AS sum, + + "Returns the number of rows in a row set. + "The following two have the same meaning. + COUNT( * ) AS count2, + COUNT(*) AS count3, + + "Chains the results in a row set. + "An optional separator can be specified + STRING_AGG( airpfrom, ', ' ) AS string_agg + +FROM zdemo_abap_flsch +WHERE carrid = 'LH' +GROUP BY carrid +INTO TABLE @DATA(agg_exp). +``` + +

⬆️ back to top

+ + +### Window Expressions + +How [window expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_expression_glosry.htm "Glossary Entry") work: + +- Define a subset of the result set (i. e. the + "[window](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_glosry.htm "Glossary Entry")") + of a database query that implements ABAP SQL +- Apply a [window function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_function_glosry.htm "Glossary Entry") - + which evaluates the rows of the window and which can, for example, + be an [aggregate + function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") + like + [`AVG`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_agg_func&sap-language=EN&sap-client=000&version=X&anchor=!ABAP_VARIANT_1@1@&tree=X) + to determine the average value - to the result set +- I. e. a window is constructed by the rows of the result set for + which all the window functions have the same result; a value is then + determined for the rows of a window + +Setup of a statement with window expressions: + +- Window function, e. g. an aggregate function like `AVG`, + followed by `OVER( ... )` (the content in the parentheses + defines the "window") +- The content in the parentheses can contain the following additions: + - Optional `PARTITION BY`: Defines the windows using a + comma-separated list of [SQL + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm); + the window function is calculated for the rows of this window; + note that if the addition is not specified, the window comprises + all rows of the result set + - Optional `ORDER BY`: Introduces both an order (you can + use `ASCENDING` and `DESCENDING`) and a frame + (as outlined below) within the current window, which further + restricts the rows for which the window function is calculated + - A window frame, which stands for a subset of rows inside a + window, can optionally be defined if `ORDER BY` is + specified; there are 3 options to define the starting and ending + frame boundaries (see the example) + +See more information on window expressions and the syntax +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_over.htm). + +Examples: +``` abap +"Example 1: A simple window is constructed in the OVER clause; +"window functions - here aggregate functions - are applied +SELECT carrid, currency, + SUM( paymentsum ) OVER( PARTITION BY carrid ) AS sum, + AVG( price AS DEC( 14,2 ) ) OVER( PARTITION BY carrid ) AS avg, + MAX( price ) OVER( PARTITION BY carrid ) AS max + FROM zdemo_abap_fli + ORDER BY carrid + INTO TABLE @DATA(win). + +"Example 2: +SELECT carrid, currency, fldate, + "Sorts the rows by some columns and counts the number of rows from + "the first row of the window to the current row. + COUNT( * ) OVER( ORDER BY currency, fldate + ROWS BETWEEN + "UNBOUNDED PRECEDING: frame starts at the first row of the window + UNBOUNDED PRECEDING + "CURRENT ROW: determines starting or ending at the current row; here, it ends + AND CURRENT ROW ) AS count1, + + "If no window frame is used, the default window frame is + "BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, + "i. e. the result of count1 equals the result of count2. + COUNT( * ) OVER( ORDER BY currency, fldate ) AS count2, + + "Sorts the rows by some columns and counts the number of rows from + "the current row to the last row of the window. + "The result is reverse numbering. + COUNT( * ) OVER( ORDER BY currency, fldate + ROWS BETWEEN CURRENT ROW + UNBOUND FOLLOWING: + "Determines the ending frame boundary, this addition specifies the last row of the window + AND UNBOUNDED FOLLOWING ) AS count_reverse, + + "Sorts the rows by some columns and calculates the rolling averages + "of a subset of rows from column price. The subset consists of the + "current row plus one preceding and one following row. Another use + "case as below example that uses prices would be that, for example, + "you can calculate the 3-day-average temperature for every day from + "a list of temperature data. + AVG( price AS DEC( 14,2 ) ) OVER( ORDER BY currency, fldate + ROWS BETWEEN + "n PRECEDING: for both start and end of frame; frame to start/end n rows above the current row + 1 PRECEDING + "n FOLLOWING: for both start and end of frame; frame to start/end n rows beneath the current row + AND 1 FOLLOWING ) AS avg + + FROM zdemo_abap_fli INTO TABLE @DATA(result). ```

⬆️ back to top

+### Null Expressions + +The [null value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm) is represented by the `NULL` operand in ABAP SQL statements. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_null.htm). + +```abap +SELECT + carrid, + carrname, + "The type of the null value is determined by the context. + "When the null value is passed to the internal table, + "it is converted to the initial value. In the first case, + "it is ' '. In the second case, it is 0.. + CASE WHEN length( carrname ) > 12 THEN char`X` + ELSE NULL + END AS long_name, + CAST( NULL AS INT1 ) AS null_val + +FROM zdemo_abap_carr +INTO TABLE @DATA(null_expr). +``` + +

⬆️ back to top

+ +## Built-In SQL Functions +- Built-in SQL functions can be called in ABAP SQL. +- The result is a value with the associated dictionary type. +- The arguments of the functions can cover one or more SQL expressions. +- For all available functions and for more information, refer to [this topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_builtin_functions.htm) in the ABAP Keyword Documentation and the subtopics. +- The functions are also covered in other cheat sheets such as the *Misc Built-In Functions* cheat sheet. + +### Numeric Functions + +[Numeric functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith_func.htm) + +``` abap +SELECT SINGLE + carrname, + + "Division, result rounded to an integer + "Result: 2 + div( 4, 2 ) AS div, + + "Division, 3rd argument: result is rounded to the specified + "number of decimals + "Result: 0.33 + division( 1, 3, 2 ) AS division, + + "Result is rounded to first greater integer + "Result: 2 + ceil( decfloat34`1.333` ) AS ceil, + + "Result is the remainder of division + "Result: 1 + mod( 3, 2 ) AS mod, + + "Result: Largest integer value not greater than the specified value + "Result: 1 + floor( decfloat34`1.333` ) AS floor, + + "Returns the absolute number + "Result: 2 + abs( int4`-2` ) AS abs, + + "Result is rounded to the specified position after the decimal separator + "Result: 1.34 + round( decfloat34`1.337`, 2 ) AS round + + FROM zdemo_abap_carr + WHERE carrid = 'AA' + INTO @DATA(numeric_functions). +``` + +

⬆️ back to top

+ +### String Functions + +[String functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string_func.htm) + +``` abap +SELECT SINGLE + carrid, "LH + carrname, "Lufthansa + url, "http://www.lufthansa.com + + "Concatenates strings, ignores trailing blanks + "Result: LHLufthansa + concat( carrid, carrname ) AS concat, + + "Concatenates strings, number denotes the blanks that are inserted + "Result: LH Lufthansa + concat_with_space( carrid, carrname, 1 ) AS concat_with_space, + + "First letter of a word -> uppercase, all other letters -> lowercase; + "note that a space and other special characters means a new word. + "Result: Http://Www.Lufthansa.Com + initcap( url ) AS initcap, + + "Position of the first occurrence of the substring specified + "Result: 6 + instr( carrname,'a' ) AS instr, + + "String of length n starting from the left of an expression; + "trailing blanks are ignored + "Result: Luft + left( carrname, 4 ) AS left, + + "Number of characters in an expression, trailing blanks are ignored + "Result: 24 + length( url ) AS length, + + "Checks if expression contains a PCRE expression; + "case-sensitive by default (case_sensitive parameter can be specified) + "Notes on the result: 1 = found, 0 = not found + "Result: 1 + like_regexpr( pcre = '\..', "Period that is followed by any character + value = url ) AS like_regex, + + "Returns position of a substring in an expression, + "3rd parameter = specifies offset (optional) + "4th parameter = determines the number of occurrences (optional) + "Result: 9 + locate( carrname, 'a', 0, 2 ) AS locate, + + "Searches a PCRE pattern, returns offset of match; + "many optional parameters: occurrence, case_sensitive, start, group + "Result: 21 + locate_regexpr( pcre = '\..', "Period followed by any character + value = url, + occurrence = 2 ) "2nd occurrence in the string + AS locate_regexpr, + + "Searches a PCRE pattern, returns offset of match + 1; + "many optional parameters: occurrence, case_sensitive, start, group + "Result: 2 + locate_regexpr_after( pcre = '.', "Any character + value = url, + occurrence = 1 ) AS locate_regexpr_after, + + "Removes leading characters as specified in the 2nd argument, + "trailing blanks are removed + "Result: ufthansa + ltrim( carrname, 'L' ) AS ltrim, + + "Counts all occurrences of found PCRE patterns + "Result: 2 + occurrences_regexpr( pcre = '\..', "Period that is followed by any character + value = url ) AS occ_regex, + + "Replaces the 2nd argument with the 3rd in an expression + "Result: Lufth#ns# + replace( carrname, 'a', '#' ) AS replace, + + "Replaces a found PCRE expression; + "more parameters possible: occurrence, case_sensitive, start + "Result: http://www#ufthansa#om + replace_regexpr( pcre = '\..', "Period that is followed by any character + value = url, + with = '#' ) AS replace_regex, + + "Extracts a string with the length specified starting from the right + "Result: hansa + right( carrname, 5 ) AS right, + + "Expands string to length n (2nd argument); trailing blanks produced + "are replaced by the characters from the (3rd) argument + "Note that if n is less than the string, the expression is truncated + "on the right. + "Result: Lufthansa### + rpad( carrname, 12, '#' ) AS rpad, + + "All trailing characters that match the character of the 2nd argument + "are removed; trailing blanks are removed, too + "Result: Lufthans + rtrim( carrname, 'a' ) AS rtrim, + + "Returns a substring; 2nd argument = position from where to start; + "3rd argument: length of the extracted substring + "Result: fth + substring( carrname, 3, 3 ) AS substring, + + "Searches for a PCRE expression and returns the matched substring + "More parameters possible: occurrence, case_sensitive, start, group + "Result: .lu + substring_regexpr( pcre = '\...', "Period that is followed by any two characters + value = url ) AS substring_regexpr, + + "All lower case letters are transformed to upper case letters + "Result: LUFTHANSA + upper( carrname ) AS upper + + FROM zdemo_abap_carr + WHERE carrid = 'LH' + INTO @DATA(string_functions). +``` + +

⬆️ back to top

+ + +### coalesce Function + +[coalesce](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_coalesce.htm) + + +```abap +"The null value is a special value that is returned by a database. It indicates an +"undefined value or result. Note that, in ABAP, there are no special null values. Do +"not confuse the null value with a type-dependent initial value. When using SELECT +"statements to read data, null values can be produced by, for example, outer joins. +"When the null values are passed to a data object, they are transformed to the +"type-dependent initial values. For more information, refer to the ABAP Keyword Documentation. +"The following example uses a left outer join to intentionally create null values. For +"this purpose, two demo database tables of the ABAP cheat sheet repository are cleared and +"populated with specific values to visualize null values. +DELETE FROM zdemo_abap_tab1. +DELETE FROM zdemo_abap_tab2. +MODIFY zdemo_abap_tab1 FROM TABLE @( VALUE #( ( key_field = 1 char1 = 'a' char2 = 'y' ) + ( key_field = 2 char1 = 'b' char2 = 'z' ) ) ). +MODIFY zdemo_abap_tab2 FROM TABLE @( VALUE #( ( key_field = 1 char1 = 'a' ) + ( key_field = 2 char1 = 'a' ) + ( key_field = 3 char1 = 'b' ) + ( key_field = 4 ) ) ). + +"Note that for the entry 'key_field = 4' no char1 value was passed. +"char1 is a shared column of the two database tables, and which is used in +"the ON condition of the join. Since there is no entry in char1 for 'key_field = 4', +"the joined values are null in that case. +"The coalesce function is used to replace null values produced by an outer join with +"a different value. +SELECT tab2~key_field, + coalesce( tab1~char1, '-' ) AS coalesced1, + coalesce( tab1~char2, '#' ) AS coalesced2, + "A coalesce function is a short form of a complex + "case distinction such as the following: + CASE WHEN tab1~char1 IS NOT NULL THEN tab1~char1 + ELSE '?' + END as coalesced3 + + FROM zdemo_abap_tab2 AS tab2 + LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 + INTO TABLE @DATA(join_w_null). + +*Example table content +*KEY_FIELD COALESCED1 COALESCED2 COALESCED3 +*1 a y a +*2 a y a +*3 b z b +*4 - # ? +``` + +

⬆️ back to top

+ +### More Functions + +More information: +- [Special functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_special_functions.htm) +- [UUID function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_uuid.htm) +- [Date and time functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_uuid.htm) +- It is also possible to call [SQL-based scalar functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_sql_scalar_glosry.htm). Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cds_scalar_func.htm). + +The following example shows a selection. Other cheat sheets such as *Misc Built-In Functions* show more snippets about date and time functions. + +``` abap +SELECT SINGLE + carrid, + + "Conversion functions + "When used: Special conversions that cannot be handled in a general + "CAST expression + + "Type conversion: string of fixed length (e.g. of type c) to variable + "length string of type string + to_clob( carrid ) AS clob, + + "Byte string -> character string + bintohex( raw`3599421128650F4EE00008000978B976` ) AS bintohex, + + "Character string -> byte string + hextobin( char`3599421128650F4EE00008000978B976` ) AS hextobin, + + "Byte field of type RAW to a byte string (BLOB) of type RAWSTRING + to_blob( raw`3599421128650F4EE00008000978B976` ) AS blob, + + "Unit and currency conversion functions + "More parameters are available. + + "Converts miles to kilometers + unit_conversion( quantity = d34n`1`, + source_unit = unit`MI`, + target_unit = unit`KM` ) AS miles_to_km, + + "Converts Euro to US dollars using today's rate + currency_conversion( + amount = d34n`1`, + source_currency = char`EUR`, + target_currency = char`USD`, + exchange_rate_date = @( cl_abap_context_info=>get_system_date( ) ) + ) AS eur_to_usd, + + "Date and time functions + add_days( @( cl_abap_context_info=>get_system_date( ) ), 4 ) AS add_days, + add_months( @( cl_abap_context_info=>get_system_date( ) ), 2 ) AS add_months, + is_valid( @( cl_abap_context_info=>get_system_date( ) ) ) AS date_is_valid, + is_valid( @( cl_abap_context_info=>get_system_time( ) ) ) AS time_is_valid, + + "UUID + uuid( ) AS uuid + +FROM zdemo_abap_carr +INTO @DATA(special_functions). +``` + +

⬆️ back to top

+ + + + + + + ## Changing Data in Database Tables ### Using INSERT @@ -1612,7 +1958,7 @@ INSERT dbtab FROM TABLE @itab. "Inserting lines from a table declared inline using the VALUE operator "as part of a host expression INSERT dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) -                                    ( comp1 = ... comp2 = ... ) ) ). + ( comp1 = ... comp2 = ... ) ) ). "ACCEPTING DUPLICATE KEYS addition: To avoid the runtime error mentioned above, "all lines that would produce duplicate entries in the database table @@ -1642,7 +1988,7 @@ UPDATE dbtab FROM TABLE @itab. "Using a host expression UPDATE dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) -                                    ( comp1 = ... comp2 = ... ) ) ). + ( comp1 = ... comp2 = ... ) ) ). "INDICATORS addition: Changing content of specific fields without overwriting "existing values of other fields @@ -1658,8 +2004,8 @@ TYPES ind_wa TYPE dbtab WITH INDICATORS comp_ind TYPE abap_bool. DATA ind_tab TYPE TABLE OF ind_wa. ind_tab = VALUE #( -       ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) -       ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) ). + ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) + ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) ). UPDATE dbtab FROM TABLE @ind_tab INDICATORS SET STRUCTURE comp_ind. @@ -1692,7 +2038,7 @@ MODIFY dbtab FROM TABLE @itab. "Using a host expression MODIFY dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) -                                    ( comp1 = ... comp2 = ... ) ) ). + ( comp1 = ... comp2 = ... ) ) ). "Inserting/Changing multiple rows based on a result set of an embedded subquery MODIFY dbtab FROM ( SELECT ... ). @@ -1725,14 +2071,14 @@ DELETE dbtab FROM TABLE @itab. "Using a host expression DELETE dbtab FROM TABLE @( VALUE #( ( comp1 = ... ) -                                    ( comp1 = ... ) ) ). + ( comp1 = ... ) ) ). ```

⬆️ back to top

### RAP-Specific ABAP SQL Variants -Find more information in the [ABAP for RAP: Entity Manipulation Language (ABAP EML)](08_EML_ABAP_for_RAP.md#abap-sql-statements-with-bdef-derived-types) cheat sheet. +There are [RAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenarap_glosry.htm)-specific variants of ABAP SQL statements that use the `MAPPING FROM ENTITY` addition. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmapping_from_entity.htm) and in the [ABAP for RAP: Entity Manipulation Language (ABAP EML)](08_EML_ABAP_for_RAP.md#abap-sql-statements-with-bdef-derived-types) cheat sheet.

⬆️ back to top

@@ -1748,7 +2094,11 @@ Find more information in the [ABAP for RAP: Entity Manipulation Language (ABAP E INTO ... ``` - [This topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql.htm) serves as the entry point for topics about ABAP SQL in the ABAP Keyword Documentation. For the full details, check the subtopics there, especially topics not covered in this cheat sheet. -- There are [RAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenarap_glosry.htm)-specific variants of ABAP SQL statements that use the `MAPPING FROM ENTITY` addition. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmapping_from_entity.htm). +- Find more topics in the ABAP Keyword Documentation such as the following: + - ABAP SQL statements can contain [SQL path expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_path_expression_glosry.htm). For more information, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_path.htm). The executable example of the CDS view entities cheat sheet includes demo SQL statements. + - Find [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_exceptions.htm) and overview on exceptions that can occur in the context of ABAP SQL statements. + - As a rule, bear in mind performance aspects when using ABAP SQL statements. Find more information in the [Performance Notes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_perfo.htm). The code snippets here only focus on syntax options. + - You can specify hierarchy data as a data source in ABAP SQL `SELECT` statements. Find more information and examples in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenselect_hierarchy_data.htm). ## Executable Example [zcl_demo_abap_sql](./src/zcl_demo_abap_sql.clas.abap) @@ -1760,4 +2110,4 @@ Find more information in the [ABAP for RAP: Entity Manipulation Language (ABAP E > - Changing data in database tables using `INSERT`, `UPDATE`, `MODIFY` and `DELETE` > - Excursions: Operands and expressions in ABAP SQL statements > - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](./README.md#%EF%B8%8F-disclaimer) +> - [Disclaimer](./README.md#%EF%B8%8F-disclaimer) \ No newline at end of file