У меня есть такая строка: aa;bb;cc

Количество символов в каждом блоке может быть разным.

; это разделитель.

Мне нужно принимать значения отдельно. Например: я хочу взять только вхождение во второй позиции (bb).

Я пробовал это:

SELECT trim(regexp_substr('aa;bb;cc', '[^;]+', 1, LEVEL)) str
   FROM dual 
CONNECT BY regexp_substr('aa;bb;cc', '[^;]+', 1, LEVEL) IS NOT NULL;

Но если я это сделаю,

SELECT * FROM (SELECT trim(regexp_substr('aa;bb;cc', '[^;]+', 1, LEVEL)) str
   FROM dual 
CONNECT BY regexp_substr('aa;bb;cc', '[^;]+', 1, LEVEL) IS NOT NULL) 
  WHERE ROWNUM = 2; 

Не работает.

1
Ork 2 Май 2019 в 14:12

2 ответа

Ты можешь использовать

with t(str) as
(
 select 'aa;bb;cc' from dual
), t2 as
(
select trim(regexp_substr(str, '[^;]+', 1, level)) str,
       level as lvl
   from t 
 connect by regexp_substr(str, '[^;]+', 1, level) is not null
) 
select str 
  from t2
 where lvl = 2;

STR
---
bb

Демонстрация

Я не советую вам использовать rownum как можно чаще, особенно запросы с подзапросами и заказами по предложениям. В вашем случае WHERE ROWNUM = 1 возвращает значение (а результат ненадежен, я имею в виду, что для реальных значений, полученных из таблиц, может быть иным, чем вы хотите, но для других равенств ROWNUM = 2 или ROWNUM = 3 даже не возвращайте значение.

1
Barbaros Özhan 2 Май 2019 в 11:37

WHERE ROWNUM = 2 никогда не вернет никакого результата, так как значение rownum вычисляется из набора результатов запроса. Но так как никогда не бывает первого ряда, ROWNUM = 2 никогда не будет достигнут.

Проще всего использовать OFFSET и LIMIT вместо этого: < Код > ВЫБЕРИТЕ ИЗ ( SELECT trim (regexp_substr ('aa; bb; cc', '[^;] +', 1, LEVEL)) str ОТ двойного CONNECT BY regexp_substr ('aa; bb; cc', '[^;] +', 1, LEVEL) НЕ ПУСТО ) OFFSET 1 ROW FETCH NEXT 1 ROWS ONLY

1
Radagast81 2 Май 2019 в 11:20