WRBTR字段在CASE中的计算会抛出最大小数点错误



我有如下选择:

SELECT FROM bseg
LEFT JOIN aufk ON ( ltrim( aufk~aufnr, '0' ) = bseg~zuonr )
JOIN bkpf ON bkpf~belnr = bseg~belnr AND bkpf~gjahr = bseg~gjahr AND bkpf~bukrs = bseg~bukrs
FIELDS bseg~bukrs, bseg~bschl, bseg~wrbtr, bseg~h_hwaer
INTO TABLE @DATA(output).

当select完成时,I遍历output表,在bschl = '50'时进行计算。

LOOP AT output ASSIGNING FIELD-SYMBOL(<output>) WHERE bschl = '50'.
<output>-wrbtr = <output>-wrbtr * ( -1 ).
ENDLOOP.

自从ABAP 7.4我可以在SQL选择中使用CASE语句。这就是我想要用来摆脱循环的方法。

SELECT FROM bseg
LEFT JOIN aufk ON ( ltrim( aufk~aufnr, '0' ) = bseg~zuonr )
JOIN bkpf ON bkpf~belnr = bseg~belnr AND bkpf~gjahr = bseg~gjahr AND bkpf~bukrs = bseg~bukrs
FIELDS bseg~bukrs,
CASE
WHEN bseg~bschl = '50' THEN  bseg~wrbtr * ( -1 )
ELSE bseg~wrbtr
END AS bseg~wrbtr, bseg~h_hwaer
INTO TABLE @DATA(output).

这是关于我如何处理上面描述的需求。

不幸的是,我得到了一个错误消息:

表达式中以WRBTR开头的最大可能位数为34位,其中有2位小数。
但是,小数位数不能超过31位和14位。

我也试过castbseg~wrbtr:

WHEN bseg~bschl = '50' THEN  CAST( bseg~wrbtr * ( -1 ) )

")" is invalid here (due to grammar).

WHEN bseg~bschl = '50' THEN  CAST( bseg~wrbtr AS test ) * ( -1 ) 

"TEST" is invalid here (due to grammar).

有人知道怎么处理这个吗?

我的答案是通过* -1设置一个标志。它不适用于与其他数的乘法。

在ABAP 7.52和S/4HANA 1709中,BSEG-WRBTR仍然是一个包含2个小数的封装的7字节数,除了END AS bseg~wrbtr导致错误"~" is invalid here (due to grammar)并且必须用END AS wrbtr替换,语法在我的系统中是有效的.

在我的系统中,输出表的内联声明选择了一个包含2位小数的封装的13字节数。它是使输出表中的位数乘以2(从7字节到13字节)的乘法。作为比较,加法只声明一个打包的8字节数。

我猜你有一个最近的S/4HANA版本,BSEG-WRBTR有更多的数字(功能称为"数量字段长度扩展"),这就是为什么乘法使内联声明产生一个无效的类型,有太多的数字。

解决方法:如果你签名而不相乘,它将保持相同的位数(在我的情况下是打包的7字节数),这种语法也应该适用于你的情况:

CASE bseg~bschl
WHEN '50' THEN - bseg~wrbtr  "<=== negative sign, is not the same logic as * -1
ELSE bseg~wrbtr
END AS wrbtr

EDIT Dec 30 -我没有在ABAP文档中找到一个明确的参考,如何为算术SQL表达式计算内联类型,它是通过搜索"up"从我所经历的行为中,我可以找到一条合乎逻辑的方式";

  • SELECT, INTO target - @DATA(dobj):

    SQL表达式的结果类型对应的ABAP类型

  • sql_exp - sql_arith(涉及+,-,*和/):

    除了任何整数操作数(见上文)外,十进制表达式至少有一个操作数类型为DEC、CURR、QUAN或p。十进制表达式中不允许使用/运算符。结果类型为DEC,长度为31,小数点后最多14位。使用关联的分配规则,它可以赋值给所有值范围足够大的数值ABAP类型,除了十进制浮点数。

  • SELECT,赋值规则:

    如果目标字段是数字数据类型,则结果字段的值转换为该数据类型,并且目标字段的值范围必须足够大。这里,在CURR、DEC或QUAN类型的结果字段中任何多余的小数点(BCD格式的数字)都被截断.

正确的CASE语法:

CASE bseg~bschl
WHEN '50' THEN  bseg~wrbtr * ( -1 )
ELSE bseg~wrbtr
END AS bseg~wrbtr

将bseg~bschl移到case和WHEN后面,只提到相等的值

在您的CASE中,CAST( bseg~wrbtr AS D34N ) * CAST( -1 AS D34N )的计算结果被放入类型为计算类型的数据对象中。

根据文档,WRBTR (ABAP类型p)的计算类型也是p,但需要注意的是:

对内联声明赋值时的计算类型p可以产生长度为8且没有小数点的数据类型p,这会产生意想不到的结果并引发异常

<解决方案/strong>:从select查询中删除内联声明INTO TABLE @DATA(output),并提前以适当的精度声明itab。

这是我对这个问题的工作解决方案。

CASE bseg~bschl
WHEN '50' THEN CAST( bseg~wrbtr AS D34N ) * CAST( -1 AS D34N )
ELSE CAST( bseg~wrbtr AS D34N )
END AS wrbtr, bseg~h_hwaer,

最新更新