Как разделить varchar2 на Oracle с помощью регулярных выражений (включая нулевые значения)? - PullRequest
0 голосов
/ 23 января 2020

Я имел дело с проблемой, которая беспокоила меня со вчерашнего дня. Я не могу разбить строки с помощью разделителя (например, трубы "|"), который содержит пустые строки. Например, моя строка foo||bar|job| Я применил запрос

select REPLACE(regexp_substr('foo||bar|job|','[^|]*(|)?',1,level),'|') output, level
from dual
connect by level <= length(regexp_replace('foo||bar|job|','[^|]+')) + 1
ORDER BY level

И все же он не возвращает хороший результат. Я получаю:

1. foo
2. 
3. 
4. bar
5. 

Я также пробовал это решение (ORACLE PL- SQL Как РАЗДЕЛИТЬ строку и ВЕРНУТЬ список, используя функцию ), но я не могу адаптировать его в строки с "|" разделитель.

with tbl(str) as (select 'foo||bar|job|' from dual ) 
select regexp_substr(str, '(.*?)(/||$)', 1, level, null, 1) element 
from tbl connect by level <= regexp_count(str, '|')+1;

В результате получается таблица, содержащая только 13 пустых строк. Что мне следует, кроме такого списка (или таблицы):

1. foo
2. 
3. bar
4. job
5.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 23 января 2020
with tbl(str) as (select 'foo||bar|job|' from dual ) 
select level, regexp_substr(str, '(.*?)(\||$)', 1, level, null, 1) e
  from tbl 
  connect by level <= regexp_count(str, '\|') + 1;

| имеет особое значение в регулярных выражениях, поэтому, если вы хотите адаптировать упомянутый ответ, вам нужно поставить перед конвейером обратный символ sh, говорящий Oracle, чтобы он воспринимался как нормальный символ. Используйте backsla sh в connect by, поэтому вы получили 14 строк вместо 5.

     LEVEL E
---------- -------------
         1 foo
         2 
         3 bar
         4 job
         5 
1 голос
/ 23 января 2020

используйте connect by с REGEXP_COUNT следующим образом:

SQL> SELECT
  2      REGEXP_SUBSTR('foo||bar|job|', '[^|]+', 1, LEVEL) AS RESULT,
  3      LEVEL
  4  FROM
  5      DUAL
  6  CONNECT BY
  7      LEVEL <= REGEXP_COUNT('foo||bar|job|', '\|') + 1;

RESULT                                                    LEVEL
---------------------------------------------------- ----------
foo                                                           1
bar                                                           2
job                                                           3
                                                              4
                                                              5

SQL>

Если вас беспокоит порядок null и фактические значения тогда вы можете использовать следующий запрос:

SQL> SELECT
  2      REPLACE(REGEXP_SUBSTR(REPLACE('foo||bar|job|', '||', '|#|'), '[^|]+', 1, LEVEL)
  3              , '#', '') AS RESULT,
  4      LEVEL
  5  FROM
  6      DUAL
  7  CONNECT BY
  8      LEVEL <= REGEXP_COUNT('foo||bar|job|', '\|') + 1;

RESULT                                                        LEVEL
-------------------------------------------------------- ----------
foo                                                               1
                                                                  2
bar                                                               3
job                                                               4
                                                                  5

SQL>

Cheers !!

...