#sql #oracle
#sql #Oracle
Вопрос:
Я получил этот запрос и хочу извлечь значение между скобками.
select de_desc, regexp_substr(de_desc, '[(. )]', 1)
from DATABASE
where col_name like '[%]';
Однако это дает мне значение в скобках, например «[TEST]». Я просто хочу «ПРОВЕРИТЬ». Как мне изменить запрос, чтобы получить его?
Ответ №1:
Третий параметр функции REGEXP_SUBSTR указывает позицию в целевой строке ( de_desc
в вашем примере), с которой вы хотите начать поиск. Предполагая, что совпадение найдено в данной части строки, это не влияет на то, что возвращается.
В Oracle 11g для функции есть шестой параметр, который, я думаю, вы пытаетесь использовать, который указывает группу захвата, которую вы хотите вернуть. Примером правильного использования может быть:
SELECT regexp_substr('abc[def]ghi', '[(. )]', 1,1,NULL,1) from dual;
Где последний параметр 1
указывает номер группы захвата, которую вы хотите вернуть. Вот ссылка на документацию, которая описывает параметр.
похоже, что в 10g нет этой опции, но в вашем случае вы можете добиться того же результата с помощью:
select substr( match, 2, length(match)-2 ) from (
SELECT regexp_substr('abc[def]ghi', '[(. )]') match FROM dual
);
поскольку вы знаете, что совпадение будет иметь ровно один лишний символ в начале и в конце. (В качестве альтернативы вы можете использовать RTRIM и LTRIM для удаления скобок с обоих концов результата.)
Комментарии:
1. Что удивительно, так это то, что 6-й параметр не упоминается в официальной документации Oracle REGEXP_SUBSTR. Спасибо, что указали, что она существует.
2. Похоже, Google приведет вас к старой документации для REGEXP_SUBSTR, но если вы сможете найти документацию 11g, вы сможете увидеть 6-й параметр: docs.oracle.com/cd/B28359_01/server.111/b28286 /…
Ответ №2:
Вам нужно выполнить замену и использовать шаблон регулярного выражения, который соответствует всей строке.
select regexp_replace(de_desc, '.*[(. )].*', '1') from DATABASE;
Комментарии:
1. ИМХО, это самый простой, легко запоминающийся, более гибкий и, следовательно, лучший способ сделать это.
2. Я бы предупредил любого, кто использует
REGEXP_REPLACE
для получения группы захвата, что, если шаблон не соответствует, Oracle вернет все значение, тогда как поведение, которое вы, вероятно, хотите, чтобы оно возвращалосьnull
. Например,REGEXP_REPLACE ('abcdefghi', '.*[(. )].*', '1')
(шаблон не соответствует) возвращаетabcdefghi
. Это однажды сбило меня с толку.3. Проблема здесь в том, что Oracle regexp не предоставляет функцию для возврата части строки, соответствующей группе захвата. Вы можете попробовать использовать рекурсивный запрос (выберите … из вкладки подключиться с помощью …), но будьте осторожны с потенциальной проблемой производительности.
4. Чтобы обойти проблему, о которой упоминает @Jared, вы можете выполнить захват «или все»
|^.*$
.regexp_replace(de_desc, '.*[(. )].*|^.*$', '1')
. Если в группе захвата 1 ничего не записано, то вся строка будет заменена на null .