Как получить n-ю строку из строк с разделителями, используя REGEXP_SUBSTR в Oracle

У меня есть строка, разделенная #, и мне нужен третий набор/ячейка в строке.

Например:

select REGEXP_SUBSTR( 'abc#def##########xyz','[^#]+', 1,1,null) from dual;

Выходы: абв

select REGEXP_SUBSTR( 'abc#def##########xyz','[^#]+', 1,2,null) from dual;

Выходы: деф.

Однако

select REGEXP_SUBSTR( 'abc#def##########xyz','[^#]+', 1,3,null) from dual;

Выходы: xyz

Но я ожидаю получить null, так как третья ячейка между ## пуста.


person Girish    schedule 10.04.2019    source источник


Ответы (2)


Это знакомая проблема. Используйте другой шаблон, как предлагает этот ответ:

select REGEXP_SUBSTR( 'abc#def##########xyz','(.*?)(#|$)', 1, 1, null, 1) from dual;

abc

select REGEXP_SUBSTR( 'abc#def##########xyz','(.*?)(#|$)', 1, 2, null, 1) from dual;

def

select REGEXP_SUBSTR( 'abc#def##########xyz','(.*?)(#|$)', 1, 3, null, 1) from dual;

(null)

select REGEXP_SUBSTR( 'abc#def##########xyz','(.*?)(#|$)', 1, 12, null, 1) from dual;

xyz

Или получить их все сразу с помощью иерархического запроса (или рекурсивного CTE):

select level as pos,
  REGEXP_SUBSTR( 'abc#def##########xyz','(.*?)(#|$)', 1, level, null, 1) as result
from dual
connect by level <= regexp_count('abc#def##########xyz', '#') + 1;

       POS RESULT              
---------- --------------------
         1 abc                 
         2 def                 
         3 (null)              
         4 (null)              
         5 (null)              
         6 (null)              
         7 (null)              
         8 (null)              
         9 (null)              
        10 (null)              
        11 (null)              
        12 xyz                 

12 rows selected. 
person Alex Poole    schedule 10.04.2019
comment
Большое спасибо @alex poole - person Girish; 16.04.2019

Как насчет комбинации SUBSTR + INSTR?

SQL> with test (col) as (select 'abc#def##########xyz' from dual)
  2  select substr(col, instr(col, '#', 1, 2) + 1,
  3                     instr(col, '#', 1, 3) - instr(col, '#', 1, 2) - 1
  4               ) third_string,
  5         --
  6         substr(col, instr(col, '#', 1, 1) + 1,
  7                     instr(col, '#', 1, 2) - instr(col, '#', 1, 1) - 1
  8               ) second_string
  9  from test;

THIRD_STRING    SECOND_STRING
--------------- ---------------
                def

SQL>

Объяснение second_string (более простой случай, поскольку на самом деле он возвращает что-то):

  • первая строка INSTR находит второе появление символа #
  • вторая строка INSTR находит 3-е появление символа # и вычитает 2-е появление (поэтому создается длина подстроки)
person Littlefoot    schedule 10.04.2019