【问题标题】:Find all matches in a varchar2()查找 varchar2() 中的所有匹配项
【发布时间】:2013-03-15 14:01:52
【问题描述】:

我有一列是 varchar2,其中包含如下数据:....[A1]...[A2]... 我想取出由[] 封装的所有以字母开头并且可以有一个或两个数字的数据,即:[B1][B23]

所以我想要类似:“WHERE 列类似于 '[__]' OR column is like '[___]'_ 不是任何值,而是字母或数字。

是否可以将它们以某种方式存储以备后用?

【问题讨论】:

    标签: sql regex oracle


    【解决方案1】:

    好问题! Here's a Fiddle 展示了如何将匹配项查询到结果集中。

    如果 Fiddle 中的查询没有意义,这里有很长的解释:)

    我正在使用一个名为 RegEx_Test 的表,其中有一列 MyVal。这是表格的内容:

    MyVal
    ------------------------------
    [A1][abc][B23][D123]a33[bx5]
    [Z15][ax0][B0][F13]R3
    [X215][A3A][J99]F33F33G24[43][R3]
    [Z99][c1][F3][d33]3x24[Y3][f13]
    [9a][D41][Q39][XX12]B27[T03][J12]
    

    你的正则表达式是这样的:\[[[:alpha:]][[:digit:]]{1,2}\]。除了 POSIX :alpha::digit: 指示符之外,它与其他答案相同,它们在国际字符集的情况下更安全。

    首先,您需要知道任何一行的最大匹配数。为此使用REGEXP_COUNT

    SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
      FROM Regex_Test
    
    MAX(REGEXP_COUNT(My...
    ----------------------
                         6
    

    使用该最大计数来获取一个“计数器”表(即下面的 SELECT ... FROM DUAL),并将计数器表与一个查询交叉连接,该查询将使用 REGEXP_SUBSTR 提取您的值。 REGEXP_SUBSTR 有一个“occurrence”参数,它将使用 Counter:

    SELECT
      MyVal,
      Counter,
      REGEXP_SUBSTR(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]', 1, Counter) Matched
    FROM Regex_Test
    CROSS JOIN (
       SELECT LEVEL Counter
       FROM DUAL
       CONNECT BY LEVEL <= (
         SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
         FROM Regex_Test)) Counters
    

    这是针对我的表运行的示例(部分结果):

    MyVal                              Counter Matched
    ---------------------------------- ------- -------
    [9a][D41][Q39][XX12]B27[T03][J12]        1 [D41]
    [9a][D41][Q39][XX12]B27[T03][J12]        2 [Q39]
    [9a][D41][Q39][XX12]B27[T03][J12]        3 [T03]
    [9a][D41][Q39][XX12]B27[T03][J12]        4 [J12]
    [9a][D41][Q39][XX12]B27[T03][J12]        5
    [9a][D41][Q39][XX12]B27[T03][J12]        6
    [A1][abc][B23][D123]a33[bx5]             1 [A1]
    [A1][abc][B23][D123]a33[bx5]             2 [B23]
    [A1][abc][B23][D123]a33[bx5]             3
    ... and so on - total is 30 rows
    

    此时,您有一个单独匹配的结果集,加上一行少于最大匹配的空值。比赛仍然有周围的括号。用一个外部查询将整个内容包围起来,该查询将过滤掉空值并删除括号,您就有了最终列表:

    SELECT SUBSTR(Matched, 2, LENGTH(Matched)-2) FROM (
      SELECT
        MyVal,
        Counter,
        REGEXP_SUBSTR(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]', 1, Counter) Matched
      FROM Regex_Test
      CROSS JOIN (
         SELECT LEVEL Counter
         FROM DUAL
         CONNECT BY LEVEL <= (
           SELECT MAX(REGEXP_COUNT(MyVal, '\[[[:alpha:]][[:digit:]]{1,2}\]'))
           FROM Regex_Test)) Counters
    ) WHERE Matched IS NOT NULL
    

    这是 Fiddle 上的查询,可以在另一个查询中使用。

    【讨论】:

      【解决方案2】:

      您可以使用REGEXP_LIKE 来查找与您的正则表达式匹配的值:

      [...] WHERE REGEXP(col_name, '\[[A-Z][0-9]{1,2}\]');
      

      【讨论】:

      • [...] WHERE REGEXP(col_name, '[[A-Z][0-9]{1,2}]');给出与 REGEXP_LIKE (col_name, '[[A-Z][0-9]{1,1}]' 相同的结果。当我插入时,第一个正则表达式操作查找 2 个数字,而第二个正则表达式操作搜索一个数字。跨度>
      • WHERE REGEXP_LIKE (col_name, '[[A-E]{1}[0-9]{2}]') 解决了!
      • 现在是一种存储 [..] 匹配项并在另一个查询中使用它们的方法吗?
      猜你喜欢
      • 1970-01-01
      • 2016-05-31
      • 2021-10-17
      • 1970-01-01
      • 2023-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      相关资源
      最近更新 更多