Oracle SQL中是否有SUBSTR替代方法

时间:2019-09-05 12:26:28

标签: sql oracle

我正在尝试提取一个字符串中的不同子字符串。对于每个用破折号(-)分隔的字符串,我都希望使用不同的字符串。

我尝试使用SUBSTR位置功能。由于有时第二个子字符串中有4个字符,因此它不起作用,因此,第三个子字符串不正确。

SELECT SUBSTR(STR, INSTR (STR, '-', -1)+ 1)

STR = F-123-A123-B12 or F-1234-A123-B12
  • 我正在尝试查询一个能给我F的查询。
  • 我需要另一个查询,如果有4个字符,它将给出123或1234
  • 我需要另一个查询才能获得A123
  • 我需要另一个查询来获取B12

我当时想我会使用一个正则表达式函数。我找不到一个。

3 个答案:

答案 0 :(得分:7)

例如:

SQL> with test (col) as
  2    (select 'F-123-A123-B12' from dual)
  3  select regexp_substr(col, '\w+', 1, level) result
  4  from test
  5  connect by level <= regexp_count(col, '-') + 1;

RESULT
--------------
F
123
A123
B12

SQL>

答案 1 :(得分:1)

您不需要正则表达式。 INSTRSUBSTR可以工作(并且速度更快):

Oracle设置

CREATE TABLE test_data ( str ) AS
  SELECT 'F-123-A123-B12'  FROM DUAL UNION ALL
  SELECT 'F-1234-A123-B12' FROM DUAL

查询1

SELECT SUBSTR( str, 1,              delimiter1 - 1              ) AS substr1,
       SUBSTR( str, delimiter1 + 1, delimiter2 - delimiter1 - 1 ) AS substr2,
       SUBSTR( str, delimiter2 + 1, delimiter3 - delimiter2 - 1 ) AS substr3,
       SUBSTR( str, delimiter3 + 1                              ) AS substr4
FROM   (
  SELECT str,
         INSTR( str, '-', 1, 1 ) AS delimiter1,
         INSTR( str, '-', 1, 2 ) AS delimiter2,
         INSTR( str, '-', 1, 3 ) AS delimiter3
  FROM   test_data
) s

输出

SUBSTR1 | SUBSTR2 | SUBSTR3 | SUBSTR4
:------ | :------ | :------ | :------
F       | 123     | A123    | B12    
F       | 1234    | A123    | B12    

如果您确实想使用正则表达式,则不需要层次查询:

查询2

SELECT REGEXP_SUBSTR( str, '[^-]+', 1, 1 ) AS substr1,
       REGEXP_SUBSTR( str, '[^-]+', 1, 2 ) AS substr2,
       REGEXP_SUBSTR( str, '[^-]+', 1, 3 ) AS substr3,
       REGEXP_SUBSTR( str, '[^-]+', 1, 4 ) AS substr4
FROM   test_data

(输出为上述查询1。)

查询3

如果您不知道会有多少定界值并且想将它们全部解析为行,那么您 still 无需使用(慢速)正则表达式或分层查询,并且可以只需将递归子查询分解子句与简单的字符串函数一起使用(并且它与定界符之间的零宽度/ NULL子字符串一起使用)

WITH substr_bounds ( str, idx, startidx, endidx ) AS (
  SELECT str,
         1,
         1,
         INSTR( str, '-', 1 )
  FROM   test_data
UNION ALL
  SELECT str,
         idx + 1,
         endidx + 1,
         INSTR( str, '-', endidx + 1 )
  FROM   substr_bounds
  WHERE  endidx > 0
)
SELECT str,
       idx,
       CASE
       WHEN endidx = 0
       THEN SUBSTR( str, startidx )
       ELSE SUBSTR( str, startidx, endidx - startidx )
       END AS substr
FROM   substr_bounds
ORDER BY str, idx

输出

STR             | IDX | SUBSTR
:-------------- | --: | :-----
F-123-A123-B12  |   1 | F     
F-123-A123-B12  |   2 | 123   
F-123-A123-B12  |   3 | A123  
F-123-A123-B12  |   4 | B12   
F-1234-A123-B12 |   1 | F     
F-1234-A123-B12 |   2 | 1234  
F-1234-A123-B12 |   3 | A123  
F-1234-A123-B12 |   4 | B12   

db <>提琴here

答案 2 :(得分:0)

如果您的字符串可能包含NULL元素,请使用此格式进行处理(请注意,列表元素2为NULL),否则您可能会在错误的位置返回以下元素:

with test (col) as 
      (select 'F--A123-B12' from dual)
    select regexp_substr(col, '(.*?)(-|$)', 1, level, null, 1) result
    from test
    connect by level <= regexp_count(col, '-') + 1;

RESULT     
-----------
F          

A123       
B12        

4 rows selected.