原文链接:原文链接
前言
在经历了长时间的停滞之后,开放式SQL的开发从沉睡中醒来,并在ABAP7.40中采取了一些主要步骤,以便包含来自SQL92的尽可能多的特性,并提供与ABAPCD的DDL的SELECT语句大致相同的功能。为了做到这一点,通过在ABAP运行时环境中引入一个新的SQL解析器来建立一个开放SQL的新基础。这样做的一个结果是,opensql在ABAP中扮演的角色与以前不同。而在7.40之前,opensql更多地被认为是ABAP语言本身的一部分,与此同时,SQL特性变得越来越明显。其中一个主要指标是宿主变量的新作用。在7.40之前,您在opensql语句中使用ABAP变量,就像在所有其他ABAP语句中一样。事实上,这有效地阻碍了进一步的发展。opensql语句在转换为本机SQL之后在数据库上执行。为了比在WHERE条件下简单地比较ABAP变量(比如在许多操作数位置上的SQL表达式)更复杂,opensql解析器必须能够清楚地区分由数据库计算的操作数和内容必须传递到数据库的ABAP变量。为了完成这一任务,opensql语句中的ABAP变量同时充分发挥了宿主变量的作用,就像静态原生SQL(execsql)中的ABAP变量一样。您可以而且应该在opensql中的ABAP主机变量前面加@。事实上,只有在这样做的情况下,才能使用从7.40版开始引入的所有新SQL特性来打开SQL。为了使opensql适合将来的应用,其他一些基本的改变被引入到opensql中,比如逗号分隔的列表和在可信的SQL子句后面添加SELECT语句。
作为这些措施的第一个好处,abap7.40已经推出了opensql的基本新特性,包括在不同操作数位置的SQL表达式或内联声明的可能性。随着abap7.50的发展,这个博客将继续介绍一些新特性(更多)。
一、宿主表达式
在几乎所有可以放置主机变量的位置,包括7.40版本的SQL表达式的操作数位置或编写SQL语句的工作区,都可以使用主机表达式
示例:…@(abap_表达式)…
宿主表达式abap\u表达式可以是任何abap表达式,即构造函数表达式、表表达式、算术表达式、字符串表达式、位表达式、内置函数、函数方法或以@为前缀的括号()内的方法链。opensql语句的宿主表达式是从左到右求值的,它们的结果会像对宿主变量的内容求值一样传递给数据库。实际上,您可以将宿主表达式视为将ABAP表达式指定给ABAP助手变量并将其用作宿主变量的捷径。下面的示例显示一个表表达式,该表达式从WHERE条件右侧的内部表中读取值。
示例:
SELECT carrid, connid, cityfrom, cityto
FROM spfli
WHERE carrid =
@( VALUE spfli-carrid( carriers[ KEY name
carrname = name ]-carrid
OPTIONAL ) )
INTO TABLE @DATA(result).
我个人喜欢以下内容:
DATA(rnd) = cl_abap_random_int=>create(
seed = CONV i( sy-uzeit ) min = 1 max = 100 ).
INSERT demo_expressions FROM TABLE @(
VALUE #(
FOR i = 0 UNTIL i > 9
( id = i
num1 = rnd->get_next( )
num2 = rnd->get_next( ) ) ) ).
在INSERT语句中构造并用随机数填充内部表。ABAP文档演示程序的一个很酷的特性…
有关详细信息,请详见宿主表达式
二、SQL表达式
在ABAP 7.50 中,SQL表达式的使用得到了扩展:
除了在SELECT列表中使用它们,你现在可以在WHERE, HAVING, ON和CASE的左手端作为CAST的操作数使用它们。意,这会把包含的宿主变量和宿主表达式作为SQL表达式的操作数处理。
以下SQL函数现可用于SQL表达式:ROUND, CONCAT, LPAD, LENGTH, REPLACE, RIGHT, RTRIM, SUBSTRING。COALESCE函数现在最多可以有255个参数。
作为WHERE条件左侧的算术表达式示例,请参见:
SELECT carrid, connid, fldate, seatsmax, seatsocc,
seatsmax – seatsocc AS seatsfree
FROM sflight
WHERE seatsmax – seatsocc > @( meth( ) )
INTO TABLE @DATA(result).
作为字符串函数的示例,参见以下使用CONCAT将列串联成一列:
SELECT CONCAT( CONCAT( carrid,
LPAD( carrname,21,’ ‘ ) ),
LPAD( url,40,’ ‘ ) ) AS line
FROM scarr
INTO TABLE @DATA(result).
由于ABAP 7.40,因此不能使用运算符&&进行这种连接。
有关详细信息,请详见SQL表达式
三、路径表达式
路径表达式是您已经从CD中知道的(duh!)。如果CDS视图公开了关联,则同一视图或另一视图可以使用路径表达式访问它。
例如,以下CDS视图在其选择列表中使用路径表达式:
@AbapCatalog.sqlViewName: ‘DEMO_CDS_USE_ASC’
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view demo_cds_use_assocs
with parameters p_carrid:s_carrid
as select from demo_cds_assoc_scarr as scarr
{
scarr.carrname,
scarr._spfli.connid,
scarr._spfli._sflight.fldate,
scarr._spfli._sairport.name }
where scarr.carrid = :p_carrid
关联的名称以下划线作为前缀,并在以下视图中定义:
@AbapCatalog.sqlViewName: ‘DEMO_CDS_ASC_CAR’
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view demo_cds_assoc_scarr
as select from scarr
association to demo_cds_assoc_spfli as _spfli
on scarr.carrid = _spfli.carrid
{
_spfli,
carrid,
carrname }
@AbapCatalog.sqlViewName: ‘DEMO_CDS_ASC_SPF’
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view demo_cds_assoc_spfli
as select from spfli
association to sflight as _sflight
on spfli.carrid = _sflight.carrid and
spfli.connid = _sflight.connid
association [1..1] to sairport as _sairport
on spfli.airpfrom = _sairport.id
{
_sflight,
_sairport,
carrid,
connid,
airpfrom }
在abap7.50中,opensql的SELECT在访问CDS视图时也可以在SELECT列表或FROM子句中使用这样的路径表达式。下面的Open SQL语句与上面的第一个CDS视图执行相同的操作:
SELECT scarr~carrname,
\_spfli-connid AS connid,
\_spfli\_sflight-fldate AS fldate,
\_spfli\_sairport-name AS name
FROM demo_cds_assoc_scarr AS scarr
WHERE scarr~carrid = @carrid
ORDER BY carrname, connid, fldate
INTO TABLE @DATA(result).
看起来没什么不同,嗯?只有点必须被反斜杠替换(正因为如此,路径表达式看起来就像网格的表达式 ) those for meshes
在编译这样一个opensql语句时,路径表达式将转换为数据库上的联接。可以在ST05中查看这点。
有关详细信息,请详见路径表达式
更多信息
这并不是ABAP7.50中开放SQL的全部内容。在一个即将到来的博客中,我将向您展示一个增强选择,这成为可能,因为INTO子句可以而且应该放在它的末尾…
总结
个人练习
*&---------------------------------------------------------------------*
*& Report YTEST01
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ytest01.
*宿主表达式
DATA(rnd) = cl_abap_random_int=>create(
seed = CONV i( sy-uzeit ) min = 1 max = 100 ).
DATA gt_demo_expressions TYPE TABLE OF demo_expressions.
gt_demo_expressions = VALUE #(
FOR i = 0 UNTIL i > 9
( id = i
num1 = rnd->get_next( )
num2 = rnd->get_next( ) ) ) .
WRITE:/ '宿主表达式'.
WRITE:/ .
LOOP AT gt_demo_expressions INTO DATA(gs_demo_expressions).
WRITE:/ gs_demo_expressions-id , gs_demo_expressions-num1, gs_demo_expressions-num2.
ENDLOOP.
*SQL表达式
SELECT concat( concat( carrid,
lpad( carrname,21,' ' ) ),
lpad( url,40,' ' ) ) AS line
FROM scarr
INTO TABLE @DATA(result).
WRITE:/ .
WRITE:/ 'SQL表达式'.
WRITE:/ .
LOOP AT result INTO DATA(ls_result).
WRITE:/ ls_result.
WRITE:/ .
ENDLOOP.
*路径表达式
SELECT scarr~carrname,
\_spfli-connid AS connid,
\_spfli\_sflight-fldate AS fldate,
\_spfli\_sairport-name AS name
FROM demo_cds_assoc_scarr AS scarr
* WHERE scarr~carrid = @carrid
ORDER BY carrname, connid, fldate
INTO TABLE @DATA(result1).
WRITE:/ .
WRITE:/ '路径表达式'.
WRITE:/ .
LOOP AT result1 INTO DATA(ls_result1).
WRITE:/ ls_result1.
WRITE:/ .
ENDLOOP.
原文链接:原文链接