Oracle: запрос, который подсчитывает вхождения всех не буквенно-цифровых символов в строке

Каков наилучший способ подсчета вхождений всех не алфавитно-цифровых символов, которые появляются в строке в столбце базы данных Oracle.

При попытке найти решение я понял, что у меня есть запрос, не связанный с проблемой, но я заметил, что могу изменить его в надежде решить эту проблему. Я придумал это:

SELECT  COUNT (*), SUBSTR(TITLE, REGEXP_INSTR(UPPER(TITLE), '[^A-Z,^0-9]'), 1)
FROM    TABLE_NAME
WHERE   REGEXP_LIKE(UPPER(TITLE), '[^A-Z,^0-9]')
GROUP BY    SUBSTR(TITLE, REGEXP_INSTR(UPPER(TITLE), '[^A-Z,^0-9]'), 1)
ORDER BY COUNT(*) DESC;

Это работает, чтобы найти ПЕРВЫЙ не алфавитно-цифровой символ, но я хотел бы подсчитать вхождения во всей строке, а не только в первом вхождении. E. г. в настоящее время мой запрос, анализирующий «a (string)», найдет одну открытую скобку, но мне нужно найти одну открытую скобку и одну закрытую скобку.

вопрос задан 28.01.2011
Moz
734 репутация

3 ответов


  • 5 рейтинг

    Существует неясная функция Oracle TRANSLATE, которая позволит вам сделать это вместо регулярного выражения:

    select a.*,
           length(translate(lower(title),'.0123456789abcdefghijklmnopqrstuvwxyz','.')) 
    from table_name a
    
    ответ дан IK., с репутацией 575, 28.01.2011
  • 4 рейтинг

    Попробуйте это:

    SELECT  a.*, LENGTH(REGEXP_REPLACE(TITLE, '[^a-zA-Z0-9]'), '')
    FROM    TABLE_NAME a
    
    ответ дан Chandu, с репутацией 62795, 28.01.2011
  • 1 рейтинг

    Наилучшим вариантом, как вы обнаружили, является использование процедуры PL / SQL. Я не думаю, что есть какой-либо способ создать выражение регулярного выражения, которое будет возвращать несколько значений, как вы ожидаете (по крайней мере, не в Oracle).

    Один из способов обойти это - использовать рекурсивный запрос для проверки каждого символа в отдельности, который можно использовать для возврата строки для каждого найденного символа. Следующий пример будет работать для одной строки:

    with d as (
       select '(1(2)3)' as str_value
       from dual)
    select char_value, count(*)
    from (select substr(str_value,level,1) as char_value
          from d
          connect by level <= length(str_value))
    where regexp_instr(upper(char_value), '[^A-Z,^0-9]'), 1) <> 0
    group by char_value;
    
    ответ дан Allan, с репутацией 14488, 31.01.2011