Db2 嵌套 JSON [英] Db2 nested JSON

查看:20
本文介绍了Db2 嵌套 JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Db2 JSON 功能,尤其是嵌套表.

I am trying to use Db2 JSON capabilities and in particular nested tables.

CREATE TABLE JSON.TEST1 (COL1 VARBINARY(2000));
INSERT INTO JSON.TEST1 (COL1) VALUES (JSON_TO_BSON(
'{"id"       : 103,                                       
  "orderDate": "2014-06-20",                       
  "items": {                                        
             "item": [ { "partNum": "872-AA",                         
                         "productName": "Lawnmower",                   
                         "quantity": 1,                                
                         "USPrice": 749.99                            
                       },                                              
                       { "partNum": "837-CM",                         
                         "productName": "Digital Camera",           
                         "quantity": 2,                                
                         "USPrice": 199.99                            
                       }                                                
                     ]                                               
            }                                                  
    }'
));

这很好用,但显然数组中的项目是硬编码的引用.

This works fine, however obviously items in the array are hardcoded references.

SELECT  id          
       ,orderDate
       ,product1
       ,product2

FROM json.TEST1 AS js,
    JSON_TABLE
      (js.COL1, 'strict $'
       COLUMNS( id                  INTEGER        PATH '$.id'
               ,orderDate           DATE           PATH '$.orderDate'
               ,product1            VARCHAR(32)    PATH '$.items.item[0].productName'
               ,product2            VARCHAR(32)    PATH '$.items.item[1].productName'
       )
ERROR ON ERROR) AS t
;

以下是我正在尝试的工作:

The following is what I am trying to get working:

SELECT  id          
       ,orderDate
       ,productName
FROM json.TEST1 AS js,
    JSON_TABLE
      (js.COL1, '$'
       COLUMNS( id                  INTEGER        PATH '$.id'
               ,orderDate           DATE           PATH '$.orderDate'
               ,NESTED 'lax $.items.item[]' 
               COLUMNS ( 
                         "productName" VARCHAR(32)
                       ) 
               )
       ) as t; 

作为参考我收到的错误

1) [Code: -104, SQL State: 42601]  An unexpected token "'lax $.items.item[]'  
               COLUMNS (  
    " was found following ",NESTED".  Expected tokens may include:  "<space>".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.26.14
2) [Code: -727, SQL State: 56098]  An error occurred during implicit system action type "2". Information returned for the error includes SQLCODE "-104", SQLSTATE "42601" and message tokens "'lax $.items.item[]'  
               COLUMNS (  
    |,N".. SQLCODE=-727, SQLSTATE=56098, DRIVER=4.26.14

推荐答案

很遗憾,您必须自己取消嵌套 JSON 数组,例如使用递归公用表表达式 (RCTE):

Unfortunately, you must unnest JSON arrays on your own, for example, with Recursive Common Table Expression (RCTE):

-- A table with JSON documents
WITH TAB (DOC_ID, DOC) AS 
(
VALUES
(
1,
'{"id"       : 103,                                       
  "orderDate": "2014-06-20",                       
  "items": {                                        
             "item": [ { "partNum": "872-AA",                         
                         "productName": "Lawnmower",                   
                         "quantity": 1,                                
                         "USPrice": 749.99                            
                       },                                              
                       { "partNum": "837-CM",                         
                         "productName": "Digital Camera",           
                         "quantity": 2,                                
                         "USPrice": 199.99                            
                       }                                                
                     ]                                               
            }                                                  
 }'
)
)
-- get a JSON array only for each record
, ITEMS_ARRAY (DOC_ID, ITEMS) AS 
(
  SELECT DOC_ID, JSON_OBJECT(KEY 'items' VALUE JSON_QUERY(DOC, '$.items.item') FORMAT JSON)
  FROM TAB
)
-- Use RCTE to unnest it
, ITEMS (DOC_ID, INDEX, ITEM) AS
(
  SELECT DOC_ID, 0, JSON_QUERY(ITEMS, '$.items[0]')
  FROM ITEMS_ARRAY
  WHERE JSON_EXISTS(ITEMS, '$.items[0]')
    UNION ALL
  SELECT I.DOC_ID, I.INDEX+1, JSON_QUERY(A.ITEMS, '$.items['|| TRIM(I.INDEX+1) ||']')
  FROM ITEMS I, ITEMS_ARRAY A
  WHERE I.DOC_ID = A.DOC_ID AND JSON_EXISTS(A.ITEMS, '$.items['|| TRIM(I.INDEX+1) ||']')
)
SELECT D.*, IT.*
--, I.*
FROM TAB T
JOIN ITEMS I ON I.DOC_ID = T.DOC_ID
-- array element to row
CROSS JOIN JSON_TABLE
  (
    I.ITEM, 'strict $' COLUMNS
    (
        PARTNUM      VARCHAR(20) PATH '$.partNum'
      , PRODCUCTNAME VARCHAR(20) PATH '$.productName' 
      , QUANTITY     INT         PATH '$.quantity'
      , USPRICE      DECFLOAT    PATH '$.USPrice'
    ) ERROR ON ERROR
  ) IT
-- other elements of original JSON to row
CROSS JOIN JSON_TABLE
  (
    T.DOC, 'strict $' COLUMNS
    (
        ID        INT  PATH '$.id'
      , ORDERDATE DATE PATH '$.orderDate'
    ) ERROR ON ERROR
  ) D
;

结果是:

|ID |ORDERDATE |PARTNUM|PRODCUCTNAME  |QUANTITY|USPRICE|
|---|----------|-------|--------------|--------|-------|
|103|2014-06-20|872-AA |Lawnmower     |1       |749.99 |
|103|2014-06-20|837-CM |Digital Camera|2       |199.99 |

db<>fiddle 示例.

创建适用于任何 JSON 数组的泛型函数很方便:

It's convenient to create a generic function suitable for any JSON array:

-- WITH A GENERIC TABLE FUNCTION

CREATE OR REPLACE FUNCTION UNNEST_JSON (P_DOC CLOB(1M), P_PATH VARCHAR(128))
RETURNS TABLE
(
  INDEX INT
, ITEM  CLOB(1M)
)
RETURN
  WITH ITEMS_ARRAY (ITEMS) AS 
(
  VALUES JSON_OBJECT(KEY 'items' VALUE JSON_QUERY(P_DOC, P_PATH) FORMAT JSON)
)
, ITEMS (INDEX, ITEM) AS
(
  SELECT 0, JSON_QUERY(ITEMS, '$.items[0]')
  FROM ITEMS_ARRAY
  WHERE JSON_EXISTS(ITEMS, '$.items[0]')
    UNION ALL
  SELECT I.INDEX+1, JSON_QUERY(A.ITEMS, '$.items['|| TRIM(I.INDEX+1) ||']')
  FROM ITEMS I, ITEMS_ARRAY A
  WHERE JSON_EXISTS(A.ITEMS, '$.items['|| TRIM(I.INDEX+1) ||']')
)
SELECT INDEX, ITEM 
FROM ITEMS
@

这样的泛型函数简化了解决方案:

Such a generic function simplifies the solution:

WITH TAB (DOC_ID, DOC) AS 
(
VALUES
(
1,
'{"id"       : 103,                                       
  "orderDate": "2014-06-20",                       
  "items": {                                        
             "item": [ { "partNum": "872-AA",                         
                         "productName": "Lawnmower",                   
                         "quantity": 1,                                
                         "USPrice": 749.99                            
                       },                                              
                       { "partNum": "837-CM",                         
                         "productName": "Digital Camera",           
                         "quantity": 2,                                
                         "USPrice": 199.99                            
                       }                                                
                     ]                                               
            }                                                  
 }'
)
,
(
2,
'{"id"       : 203,                                       
  "orderDate": "2014-06-20",                       
  "items": {                                        
             "item": [ { "partNum": "002-AA",                         
                         "productName": "Lawnmower",                   
                         "quantity": 10,                                
                         "USPrice": 749.99                            
                       },                                              
                       { "partNum": "002-BB",                         
                         "productName": "Digital Camera",           
                         "quantity": 20,                                
                         "USPrice": 199.99                            
                       }                                                
                     ]                                               
            }                                                  
 }'
)
)
SELECT T.DOC_ID, A.INDEX, D.*, IT.* 
FROM 
  TAB T
-- unnesting
, TABLE(UNNEST_JSON(T.DOC, '$.items.item')) A
-- array element to row
, JSON_TABLE
  (
    A.ITEM, 'strict $' COLUMNS
    (
        PARTNUM      VARCHAR(20) PATH '$.partNum'
      , PRODCUCTNAME VARCHAR(20) PATH '$.productName' 
      , QUANTITY     INT         PATH '$.quantity'
      , USPRICE      DECFLOAT    PATH '$.USPrice'
    ) ERROR ON ERROR
  ) IT
-- other elements of original JSON to row
, JSON_TABLE
  (
    T.DOC, 'strict $' COLUMNS
    (
        ID        INT  PATH '$.id'
      , ORDERDATE DATE PATH '$.orderDate'
    ) ERROR ON ERROR
  ) D;

结果是:

|DOC_ID|INDEX|ID |ORDERDATE |PARTNUM|PRODCUCTNAME  |QUANTITY|USPRICE|
|------|-----|---|----------|-------|--------------|--------|-------|
|1     |0    |103|2014-06-20|872-AA |Lawnmower     |1       |749.990|
|1     |1    |103|2014-06-20|837-CM |Digital Camera|2       |199.990|
|2     |0    |203|2014-06-20|002-AA |Lawnmower     |10      |749.990|
|2     |1    |203|2014-06-20|002-BB |Digital Camera|20      |199.990|

这篇关于Db2 嵌套 JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆