大数跨境
0
0

直接SQL你的JSON字符串

直接SQL你的JSON字符串 建广技师
2025-05-15
0
导读:升级HANA数据库后,想必不少项目保存接口日志,是用STRING字符串来保存吧。过去为了保存一个未知长度的字符串,还是挺费劲的,并且不利于查询。现在用了STRING字符串来保存,相比一定方便了不少吧。

文本参考文档:

https://help.sap.com/docs/HANA_SERVICE_CF/7c78579ce9b14a669c1f3295b0d8ca16/f8f6916b5c434a6fbd1bb7e0dc65acd4.html?locale=en-US

 

升级HANA数据库后,想必不少项目保存接口日志,是用STRING字符串来保存吧。过去为了保存一个未知长度的字符串,还是挺费劲的,并且不利于查询。现在用了STRING字符串来保存,相比一定方便了不少吧。

好吧,我承认,很长一段时间STRING唯一的优点就是直接明文保存字符串,模糊查询的时候确实挺方便,如果你不是很在乎效率的话。但有的时候,我们需要查询历史上的一些东西,比如翻出来某个未知时间段的凭证,这个时候模糊查询就不是很好用了。已经是HANA了,一定会有一个更加轻松的方式来解析JSON了吧?

是的,我的朋友,是的!HANA SQL Script了解一下!

虽然ABAP的SQL依旧贫弱,但只要放弃我们的老朋友,就可以变强。HANA的SQL Script有一个叫JSON_TABLE的语法,它可以帮助你将JSON解析成合适的数组进行输出。我们现在搭建一个例子。

日志表:

简化的日志表,name假设是区分接口,json就是传入的json字符串。

解析保存表:

定义一个表类型和结构,后面会用到。

然后写个程序保存一个JSON

{

  "item": [

    {

      "ebeln": 1,

      "ekpo": [

        {

          "ebelp": 10

        },

        {

          "ebelp": 20

        }

      ]

    },

    {

      "ebeln": 2,

      "ekpo": [

        {

          "ebelp": 30

        },

        {

          "ebelp": 40

        }

      ]

    }

  ]

}

 

好,准备工作完成,我们需要怎么解析这个JSON呢?

因为我们的日志解析程序大多是ABAP环境下,所以这里需要用AMDP的方式去运行HANA SQL Script。AMDP的类开发不能用SE24,需要在Esclipse上进行(必须吐槽下SAP,我真没觉得在SE24上开发这个类和在Esclipse上有啥区别)。

下面是类代码:

CLASSztest_amdp DEFINITION

  PUBLIC

  FINAL

  CREATE PUBLIC .

 

  PUBLIC SECTION.

    INTERFACES if_amdp_marker_hdb.

    CLASS-DATA: lt_ekko TYPE zty_t_ekpo.

    METHODS select_ztlog IMPORTING VALUE(clnt)    TYPE mandt

                         EXPORTING VALUE(lt_ekko) TYPE zty_t_ekpo.

ENDCLASS.

 

 

CLASS ztest_amdp IMPLEMENTATION.

  METHOD select_ztlog

         BY DATABASE PROCEDURE FOR HDB

         LANGUAGE SQLSCRIPT

         OPTIONS READ-ONLY

         USING ztlog.

 

    lt_ekko =

        select * FROM json_table( ( SELECT json

                                      FROM ZTLOG

                                      WHERE mandt = clnt

                                      AND   name = 1

                                      ORDER BY name ),'$.item[*]'

               COLUMNS

                (

                    EBELN nvarCHAR( 10 ) PATH'$.ebeln',

                    NESTEDPATH'$.ekpo[*]'

                       COLUMNS

                        (

                            EBELP nvarCHAR( 5 ) PATH'$.ebelp'

                        )

                )

                ) as lt_ekko

                where ebeln = 2;

 

 

  ENDMETHOD.

ENDCLASS.

 

 

首先我们的目标是将JSON中,ebeln为2的订单取出来,放在表里。已知订单都在item这个表中,订单行ebelp是个嵌套数组,那么我们要怎么取数,将订单号和订单行放在一个表里面呢?

首先是划定下最基础的取数范围,我们要取ztlog表name为1,client号是001的数据,然后指定json这个表字段。其实client号取决于实际你存放数据的客户端号。

这里我们变形下方便理解。

如果不需要对ztlog过滤,这里可以直接指向ztlog的json字段,方法就是<表.字段>。逗号后面的'$.item[*]',表示要取json结构中item这个数组。

这里推荐阅读官方文档配合理解

Description

Queries a JSON text and presents it as a relational table.

The following tokens are supported in  :

Token

Description

Example

$

The current context item.

'$'

.

The member of an object.

'$.item.description'

[

The array index specifier (open).

 

]

The array index specifier (closed).

'$[1]'

'$.item.list[1]'

to

The array index range.

'$[3 to 5]'

= '$[3,4,5]'

*

The wild card.

'$.*.description'

'$.item.list[*]'

这一段就是取我们的json内容了。参考json格式,ebeln这个字段是在item.ebeln这个字段上,ebelp在item.ekpo[*]这个数组里,因此,获取EBELN的值时,只需要简单的将EBELN的值,指定格式,指定路径取出即可。但是EBELP,就需要用NESTED进行嵌套字段的读取。

NESTED PATH可以多次使用,这样可以将多个表或结构放入到一个解析表中。不过需要注意两点,一是层级。例如本次案例,我们取的都是json中item下的数据,NESTED PATH不能取到item外面的数据。其次就是如果你打算NESTED PATH平级的多个个表,数据量最后会爆炸的,使用的时候需要想清楚你要做什么。比较建议的做法就是NESTED PATH多个平级的结构,一个平级的数组。

最后的AS别名不是必须的。

最后的where是对解析出来的json值进行过滤。这里只取ebeln为2的值。

这里的转换类型,参考官方文档

Specifies the data type.



 ::= 

BIGINT

 | DATE

 | DECIMAL

 | DOUBLE

 | INT

 | NVARCHAR ( )

 | SECONDDATE

 | SMALLDECIMAL 

 | TIME

 | TIMESTAMP

 | VARCHAR ( )

这里EBELN和EBELP都是NUMC的类型字段,所以转换格式时要用NVARCHAR,并指定长度

我们看下运行效果:

可以看到过滤效果非常完美。经过测试,如果不限定ztlog.name的取值,可以成功将ebeln=2的30,40,50,60行都取到LT_EKKO中。

需要注意的是,这里的返回表限制为扁平表。也就是说,你可以将嵌套的json解析为不嵌套的表,但是不能将嵌套结构本身解析出来。

【声明】内容源于网络
0
0
建广技师
开放、互助、分享。欢迎和我们一起探究讨论关于企业数字化转型的创新技术话题。 -- JGDT Technology Innovation Team
内容 63
粉丝 0
建广技师 开放、互助、分享。欢迎和我们一起探究讨论关于企业数字化转型的创新技术话题。 -- JGDT Technology Innovation Team
总阅读6
粉丝0
内容63