【问题标题】:Searching and Substrings in SQLSQL 中的搜索和子字符串
【发布时间】:2013-11-08 14:41:15
【问题描述】:

我想在 DB2 for i(以前称为 iSeries 或 AS/400)上使用 SQL 从字符串中提取值。

字符串包含类似 JSON 的分隔键:值对列表。示例:

("EventType":"XYZ","EffectiveDate":20131000,"ClientNo":2012020860902)

给定一个键字符串,例如“事件类型”,我想找到冒号 (':') 后面的值,在本例中为“XYZ”。但请记住,我的密钥字符串可能并不总是“事件类型”。

【问题讨论】:

标签: sql substring ibm-midrange db2-400


【解决方案1】:
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
;

【讨论】:

  • 如果您总是想要第一项,这很好。假设您不知道“EventType”可能出现在哪里。假设您要查找的并不总是“EventType”。
  • AS400 中没有 INSTR
【解决方案2】:

由于 INSTR() 不可用,它不能与 i 上的 DB2 一起使用。但是,可以使用 POSSTR(),它可以在字符串中定位搜索字符串的位置。 LENGTH() 函数可以给出搜索字符串的长度。这两个值一起基本上说明了冒号的位置。

如果知道冒号的位置,就可以确定下一个逗号的位置;并表示要提取的子字符串的长度。

所需的搜索字符串配对值的位置可能会使用:

POSSTR(str, 'EffectiveDate') +
  LENGTH('EffectiveDate') + 2 

“+ 2”让我们超过了 搜索字符串 的结束引号和冒号。我们在配对值的第一个字符。我们称这个表达式为“exprA”。 (当然,search-string 本身可能是一个宿主变量,而不是一个字面常量。)

使用 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)' , ')', ',' )

用逗号替换右括号,一切都应该工作。

但是,在我看来,通过一些相当简单的程序代码来完成这样的过程可能会更好。创建一个外部函数并完成它。

【讨论】:

    【解决方案3】:

    我支持创建一个函数来进行键/值解析的动议,因此您最终不会得到到处都是代码来执行此操作。我不同意许多人认为所述功能必须以高级语言驻留在数据库之外的趋势。如果您使用 SQL 函数来执行键/值解析,最好是表函数,因为它们比标量函数更灵活,任何访问数据库的语言或请求程序应用程序都可以访问该函数,并且对该表函数的引用甚至可以捆绑在将使用解析值的同一 SQL 语句中。当然,客户端键/值 HLL 解析器也应该存在于那些需要并且不需要引用数据库的应用程序中。

    【讨论】:

    • 在 IBM i 上,可以编写 HLL 函数并将其注册为 SQL 用户定义函数,从而将这种逻辑保留在 DB 中。放在视图中,使用起来更方便。
    猜你喜欢
    • 2017-02-09
    • 2014-10-02
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2019-10-06
    相关资源
    最近更新 更多