我想在 DB2 for i(以前称为 iSeries 或 AS/400)上使用 SQL 从字符串中提取值。
该字符串包含类似 JSON 的分隔键:值对列表。例子:
("EventType":"XYZ","EffectiveDate":20131000,"ClientNo":2012020860902)
给定一个键字符串,例如“事件类型”,我想找到冒号 (':') 之后的值,在本例中为“XYZ”。但请记住,我的密钥字符串可能并不总是“事件类型”。
我想在 DB2 for i(以前称为 iSeries 或 AS/400)上使用 SQL 从字符串中提取值。
该字符串包含类似 JSON 的分隔键:值对列表。例子:
("EventType":"XYZ","EffectiveDate":20131000,"ClientNo":2012020860902)
给定一个键字符串,例如“事件类型”,我想找到冒号 (':') 之后的值,在本例中为“XYZ”。但请记住,我的密钥字符串可能并不总是“事件类型”。
SELECT SUBSTR( str,
INSTR(str, ':') + 1,
INSTR(str, ',') - INSTR(str, ':') - 1
) AS str_result
FROM
(
SELECT '("EventType":"XYZ","EffectiveDate":20131000,"ClientNo":2012020860902)' str
FROM sysibm.sysdummy1
) t
;
我支持创建一个函数来进行键/值解析的动议,所以你最终不会到处都是代码来做这件事。我不同意许多人认为所述功能必须以高级语言驻留在数据库之外的趋势。如果您使用 SQL 函数来执行键/值解析,最好是表函数,因为它们比标量函数更灵活,任何访问数据库的语言或请求程序应用程序都可以访问该函数,并且对该表函数的引用甚至可以捆绑在将使用解析值的同一 SQL 语句中。当然,客户端键/值 HLL 解析器也应该存在于那些需要并且不需要引用数据库的应用程序中。
由于 INSTR() 不可用,它不能与 i 上的 DB2 一起使用。但是,可以使用 POSSTR(),它可以在字符串中定位搜索字符串的位置。LENGTH() 函数可以给出搜索字符串的长度。这两个值一起基本上说明了冒号的位置。
如果知道冒号在哪里,就可以确定下一个逗号的位置;并表示要提取的子字符串的长度。
所需搜索字符串配对值的位置可能使用:
POSSTR(str, 'EffectiveDate') +
LENGTH('EffectiveDate') + 2
“+ 2”让我们越过搜索字符串和冒号的右引号。我们在配对值的第一个字符。我们称这个表达式为“exprA”。(当然,搜索字符串本身可能是一个宿主变量而不是一个文字常量。)
使用 exprA 的值,我们可以从该位置开始提取并延伸到整个字符串的末尾。此时我们不需要知道配对值的长度。我们将引用它只是为了给我们找到下一个逗号的良好起点。该逗号将告诉我们配对值的长度。
SUBSTR( str, exprA )
我们称之为“exprB”。它将给出一个中间值,该值具有我们想要的从最左边开始的配对值。现在我们可以想到这样的事情:
POSSTR( exprB, ',' ) - 1
这将定位我们提取的子字符串中的第一个逗号。使用“- 1”,它会退回到配对值的结束字符并有效地提供其长度。我们称之为“exprC”。现在我们可以想到一些看起来像这样的代码:
SUBSTR( exprB ,
1 ,
exprC
)
我们生成 exprB 以在位置 1 中获取具有所需配对值的初始子字符串,并通过使用 exprC 提供长度来从中取出子字符串。现在我们需要扩展我们的表达式并查看整个混乱:
SELECT SUBSTR(
SUBSTR( str,
POSSTR(str, 'EffectiveDate') +
LENGTH('EffectiveDate') + 2
) ,
1 ,
POSSTR( SUBSTR( str,
POSSTR(str, 'EffectiveDate') +
LENGTH('EffectiveDate') + 2
),
','
) - 1
) AS str_result
现在需要的是 SELECT 可以选择 FROM 的东西。我们可以使用上面提供的短语:
FROM
(
SELECT '("EventType":"XYZ","EffectiveDate":20131000,"ClientNo":2012020860902)' str
FROM sysibm.sysdummy1
) t
;
但是,仍然存在一个小问题。有三个示例值对。前两个可以正常处理,但任何系列中的最后一对都不会有尾随逗号供 'exprC' 定位;POSSTR() 函数将返回零。它可以通过在混乱中添加一个丑陋的 CASE 结构来处理,但它看起来已经足够复杂了。最简单的方法可能是确保出现尾随逗号。如果样本值有效,最简单的方法可能是:
REPLACE( '("EventType":"XYZ","EffectiveDate":20131000,"ClientNo":2012020860902)' , ')', ',' )
用逗号替换右括号,一切都应该工作。
然而,在我看来,像这样的过程可能最好通过一些相当简单的程序代码来完成。创建一个外部函数并完成它。