REGEX для выбора n-го значения из списка, допускающего нули
Я использую REGEXP_SUBSTR()
вернуть n-е значение из списка через запятую. Это прекрасно работает, когда присутствуют все значения, но не работает, если элемент имеет значение null. Вот пример, который работает, когда присутствуют все значения, и я выбираю второе вхождение из 1 или более символов, которые не являются запятыми:
SQL> select REGEXP_SUBSTR('1,2,3,4,5,6', '[^,]+', 1, 2) data
2 from dual;
D
-
2
Но когда второе значение равно нулю, я действительно получаю третий элемент в списке, что, конечно же, является вторым появлением 1 или более символов, которые не являются запятыми. Однако мне нужно вернуть NULL, так как 2-й элемент пуст:
SQL> select REGEXP_SUBSTR('1,,3,4,5,6', '[^,]+', 1, 2) data
2 from dual;
D
-
3
Если я изменю регулярное выражение так, чтобы оно содержало ноль или более символов вместо 1 или более, оно также не будет работать для чисел после нуля:
SQL> select REGEXP_SUBSTR('1,,3,4,5,6', '[^,]*', 1, 4) data
2 from dual;
D
-
3
Мне нужно учесть нулевое значение, но, похоже, не могу понять синтаксис правильно. Логически мне нужно вернуть то, что находится до n-го вхождения запятой, независимо от того, присутствуют данные или нет (и учесть последнее значение также). Есть идеи?
2 ответа
Спасибо тем, кто ответил. Изучив ваши ответы и ответы по предоставленной ссылке, я пришел к следующему решению:
SQL> select REGEXP_SUBSTR('1,,3,4,5', '(.*?)(,|$)', 1, 2, NULL, 1) data
2 from dual;
Data
----
Который может быть описан как "посмотрите на 2-е вхождение необязательного набора из нуля или более символов, за которым следует запятая или конец строки, и верните 1-ую подгруппу (которая представляет собой данные без запятой или конца линия).
Я забыл упомянуть, что я тестировал ноль в разных позициях, несколько нулей, выбирая разные позиции и т. Д.
Единственное предостережение, которое я могу найти, это то, что если поле, которое вы ищете, больше доступного числа, оно просто возвращает NULL, поэтому вам нужно знать об этом. Не проблема для моего случая.
РЕДАКТИРОВАТЬ: Я обновляю принятый ответ в интересах будущих искателей, которые могут наткнуться на это.
Следующим шагом является инкапсуляция кода, чтобы он мог быть превращен в более простую, многократно используемую функцию. Вот источник функции:
FUNCTION GET_LIST_ELEMENT(string_in VARCHAR2, element_in NUMBER, delimiter_in VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS
BEGIN
RETURN REGEXP_SUBSTR(string_in, '(.*?)(\'||delimiter_in||'|$)', 1, element_in, NULL, 1);
END GET_LIST_ELEMENT;
Это скрывает сложность регулярных выражений от разработчиков, которым это может быть не совсем удобно, и делает код чище в любом случае при использовании. Назовите это так, чтобы получить 4-й элемент:
select get_list_element('123,222,,432,555', 4) from dual;
Как насчет чего-то такого брутального:
select REGEXP_SUBSTR(replace('1,,3,4,5,6', ',,', ',NULL,'), '[^,]+', 1, 2) data
from dual
Это возвращает строковое значение. Вы можете получить настоящий NULL
используя случай:
select (case when REGEXP_SUBSTR(replace('1,,3,4,5,6', ',,', ',NULL,'), '[^,]+', 1, 2) = 'NULL'
then NULL
else REGEXP_SUBSTR(replace('1,,3,4,5,6', ',,', ',NULL,'), '[^,]+', 1, 2)
end)
from dual;
Там может быть regexp_
Единственное решение, но это то, что первым приходит на ум.