当所有 JSON 字段键未知/任意/随机时将 JSON 转换为表

问题描述 投票:0回答:1

Oracle 中有一个表,其中有大量行,其中包含具有未知/任意/随机字段键的 JSON 对象!

基本上这些 JSON 对象是工业产品规范。有超过20k个类别和2M个产品。 JSON 看起来像

{"max. temp.": "40 F", "I.D.": "1/3 in", ...}

如何将

{ "a": 8, "b":27 }
这样的 JSON 转换为如下表:

key | val
--- | ---
a   | 8
b   | 27

如果所有 JSON 字段键都是未知/任意/随机?

sql oracle plsql
1个回答
0
投票

如果您的 json 规范是按照问题中所述构建的 - 可以选择使用递归 cte-s 和良好的旧字符函数来提取键和值:Substr()、Instr()、Replace()、...

--      S a m p l e    D a t a : 
Create Table specs ( product_id Number(6), spec VarChar2(4000) );
Insert Into specs
      Select 1, '{"max.temp.": "40 F", "I.D.": "1/3 in"}' From Dual Union All
      Select 2, '{"a": 8, "b":27 }' From Dual Union All
      Select 3, '{"energ.eff.class": "A++", "some other spec":"27", "status": "OK" }' From Dual
WITH      --  R e c u r s i v e    C T E s :
    keys ( pass, product_id, spec, keys, rest, total_spec) AS
      ( Select 1, product_id, spec, 
               Replace(Replace(SubStr(spec, 1, InStr(spec, ':', 1, 1)-2), '{ "', ''), '{"', '') as keys,
               SubStr(spec, Instr(spec, ',', 1, 1)+1) as rest,
               Length(spec) - Length(Replace(spec, ':', ''))  as total_spec
        From   specs
       UNION ALL 
        Select pass + 1, product_id, spec, 
               Replace(Replace(SubStr(rest, 1, InStr(rest, ':', 1, 1)-2), ' "', ''), '*') as keys, 
               SubStr(rest, Instr(rest, ',', 1, 1)+1) as rest,
               total_spec
        From   keys
        Where  pass < total_spec
      ), 
    vals ( pass, product_id, spec, vals, rest, total_spec) AS
      ( Select 1, product_id, spec, 
               Replace(LTRIM(SubStr(spec, InStr(spec, ':', 1, 1)+1, ( InStr(spec, ',', 1, 1) - InStr(spec, ':', 1, 1) ) - 1 )), '"', '')  as vals,
               SubStr(spec, Instr(spec, ',', 1, 1)+1) as rest,
               Length(spec) - Length(Replace(spec, ':', ''))  as total_spec
        From   specs  
       UNION ALL
        Select pass + 1, product_id, spec, 
               Replace(Replace(LTRIM(SubStr(rest, InStr(rest, ':', 1, 1)+1, ( InStr(spec, ',', 1, 1) - InStr(spec, ':', 1, 1) ) - 1) ), '"', ''), ',', '')  as vals,
               SubStr(rest, Instr(rest, ',', 1, 1)+1) as rest,
               total_spec
        From   vals
        Where  pass < total_spec
      )
--      M a i n    S Q L : 
Select    s.product_id, k.keys as key, v.vals as val
From      specs s
Left Join keys k ON(k.product_id = s.product_id)
Left Join vals v ON(v.product_id = s.product_id And v.pass = k.pass)
Order By  s.product_id, k.pass
/*      R e s u l t : 
PRODUCT_ID  KEY               VAL
----------  ----------------  -------------
         1  max.temp.         40 F
         1  I.D.              1/3 i
         2  a                 8
         2  b                 27
         3  energ.eff.class   A++
         3  some other spec   27
         3  status            OK

请参阅此处的小提琴

© www.soinside.com 2019 - 2024. All rights reserved.