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 字段键都是未知/任意/随机?
如果您的 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
请参阅此处的小提琴。